0

在 WPF 中,我有一个 2 列的 ListView,第一列需要是一个按钮。如果我错了,请纠正我,但我发现在 ListView 中实现按钮的唯一方法是使用 DataTemplate。我发现的问题是当它们与 DataTemplate 映射时,我无法维护我的原始按钮属性,因此我不得不使用绑定来重新映射每个单独的属性(包括自定义属性,因为我实际上使用的是自定义用户控件它继承自 Button)。这似乎与手动映射所有属性无关,所以也许有更好的方法来自动保留这些属性?

这是我的测试代码:

public MainWindow() {
    InitializeComponent();

    ObservableCollection<ScreenRequest> screenRequests = new ObservableCollection<ScreenRequest>() {
        new ScreenRequest("A", "1"),
        new ScreenRequest("B", "2")
    };
    myListView.ItemsSource = screenRequests;
}   

public class ScreenRequest {
    public CustomButton ScreenButton { set; get; }
    public string Details { set; get; }

    public ScreenRequest(string buttonText, string customProperty) {
        this.ScreenButton = new CustomButton();
        this.ScreenButton.Content = buttonText;
        this.ScreenButton.CustomProperty = customProperty;
        this.ScreenButton.Click += new RoutedEventHandler(InitiateScreenRequest);
    }

    private void InitiateScreenRequest(object sender, RoutedEventArgs e) {
        CustomButton screenBtn = (CustomButton)sender;
        screenBtn.Content = "BUTTON TEXT CHANGED";
    }
}   

public class CustomButton : Button  {
    public string CustomProperty { get; set; }
}

和 XAML:

<Window...
...
    <Window.Resources>
        <DataTemplate x:Key="ButtonTemplate">
            <local:CustomButton Content="{Binding ScreenButton.Content}"/>
        </DataTemplate>
    </Window.Resources>
    <Grid x:Name="grdMain">
    ...
        <ListView...
            <ListView.View>
                <GridView x:Name="gridView">
                    <GridViewColumn CellTemplate="{StaticResource ButtonTemplate}" Width="Auto" Header="Screen" HeaderStringFormat="Screen"/>
                    <GridViewColumn Header="Details" HeaderStringFormat="Details" DisplayMemberBinding="{Binding Details}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

所以我的问题是:

  1. 我是否必须手动映射 CustomButton 中的每个属性才能将其转移到 DataTemplate 中,或者它们是自动持久化属性的包罗万象?
  2. 如何在绑定中映射 CustomProperty 属性以使其与按钮保持一致?我为此使用 DependencyProperty 吗?
  3. 如何维护我的单击事件,以便单击 GridView 中的按钮将调用 InitiateScreenRequest 函数?理想情况下,我希望为所有按钮声明一个方法,但我还没有达到这一点。

任何帮助或了解列表视图中的按钮将不胜感激。

4

1 回答 1

2
<Window x:Class="MiscSamples.TonyRush"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TonyRush" Height="300" Width="300">
    <ListView ItemsSource="{Binding}">
        <ListView.View>
            <GridView>
                <GridViewColumn Width="Auto" Header="Screen" HeaderStringFormat="Screen">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Button Command="{Binding SomeAction}" Content="{Binding ActionDescription}" Width="100"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Details" HeaderStringFormat="Details" DisplayMemberBinding="{Binding Details}" Width="100"/>
            </GridView>
        </ListView.View>
    </ListView>
</Window>

代码背后:

 public partial class TonyRush : Window
    {
        public TonyRush()
        {
            InitializeComponent();
            DataContext = new List<ScreenRequest>
                              {
                                  new ScreenRequest() {ActionDescription = "Click Me!"},
                                  new ScreenRequest() {ActionDescription = "Click Me Too!"},
                                  new ScreenRequest() {ActionDescription = "Click Me Again!!"},
                              };
        }
    }

视图模型:

public class ScreenRequest: INotifyPropertyChanged
    {
        public Command SomeAction { get; set; }

        private string _actionDescription;
        public string ActionDescription
        {
            get { return _actionDescription; }
            set
            {
                _actionDescription = value;
                NotifyPropertyChanged("ActionDescription");
            }
        }

        private string _details;
        public string Details
        {
            get { return _details; }
            set
            {
                _details = value;
                NotifyPropertyChanged("Details");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public ScreenRequest()
        {
            SomeAction = new Command(ExecuteSomeAction) {IsEnabled = true};
        }

        //public SomeProperty YourProperty { get; set; }

        private void ExecuteSomeAction()
        {
            //Place your custom logic here based on YourProperty
            ActionDescription = "Clicked!!";
            Details = "Some Details";
        }
    }

关键部分:Command类:

//Dead-simple implementation of ICommand
    //Serves as an abstraction of Actions performed by the user via interaction with the UI (for instance, Button Click)
    public class Command : ICommand
    {
        public Action Action { get; set; }

        public void Execute(object parameter)
        {
            if (Action != null)
                Action();
        }

        public bool CanExecute(object parameter)
        {
            return IsEnabled;
        }

        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                if (CanExecuteChanged != null)
                    CanExecuteChanged(this, EventArgs.Empty);
            }
        }

        public event EventHandler CanExecuteChanged;

        public Command(Action action)
        {
            Action = action;
        }
    }

结果:

在此处输入图像描述

笔记:

看看 UI 与数据和功能的分离程度。这是 WPF 的方式。切勿将 UI 与数据/业务代码混为一谈。

ViewModel 中的Command用作Button. ViewModel 不知道 aButton是什么,也不应该知道。如果您需要更多详细信息,请告诉我。

于 2013-03-28T21:26:11.863 回答