4

我有以下要求:

  1. 窗口将显示一个ListView包含多个项目。
  2. 用户应该能够选中(复选框)任何项目。a) 如果是一项,则应取消选中并禁用所有项。b) 如果选中的项目未选中,则应启用所有项目。

到目前为止,我有以下不完整的代码。

主窗口 XAML:

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="520.149" Width="732.463">
    <Window.Resources>
        <ResourceDictionary Source="MainWindowResource.xaml" />
    </Window.Resources>

    <Grid>
     <ListView x:Name="myListBox" ItemTemplate="{StaticResource OfferingTemplate}">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Columns="3" VerticalAlignment="Top"/>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
        </ListView>
    </Grid>
</Window>

ListView 的数据模板:

<DataTemplate x:Key="OfferingTemplate">
    <StackPanel>
        <Grid IsEnabled="{Binding IsEnabled}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="8"></ColumnDefinition>
                <ColumnDefinition Width="120"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="40"></RowDefinition>
                <RowDefinition Height="50"></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
            </Grid.RowDefinitions>
            <Rectangle Grid.Column="0" Grid.RowSpan="3" Fill="#F4CA16" />
            <Label
                Grid.Column="1"
                Grid.Row="0"
                Content="{Binding Title}"
                FontSize="18" FontWeight="Bold"
                Margin="0,0,0,0" />
            <TextBlock
                Grid.Column="1"
                Grid.Row="1"
                FontSize="10"
                Text="{Binding Description}"
                Foreground="Black"
                TextWrapping="WrapWithOverflow"
                Margin="5,0,0,0" />
            <CheckBox
                Grid.Column="1"
                Grid.Row="2"
                FontSize="14"
                IsChecked="{Binding IsSelected}"
                VerticalAlignment="Bottom"
                Margin="5,0,0,0">

                <TextBlock Text="Select" Margin="0,-2,0,0"/>
            </CheckBox>
        </Grid>
    </StackPanel>
</DataTemplate>

模型:

class MyModel
{
    public string Title { get; set; }
    public string Description { get; set; }
    public bool IsSelected { get; set; }
    public bool IsEnabled { get; set; }
}

视图模型:

class MyViewModel : INotifyPropertyChanged
{
    private MyModel offering;

    public MyViewModel()
    {
        offering = new MyModel();
    }

    public int ID { get; set; }
    public string Title
    {
        get { return offering.Title; }
        set
        {
            offering.Title = value;
            RaisePropertyChanged("Title");
        }
    }
    public string Description
    {
        get { return offering.Description; }
        set
        {
            offering.Description = value;
            RaisePropertyChanged("Description");
        }
    }
    public bool IsSelected
    {
        get { return offering.IsSelected; }
        set
        {
            offering.IsSelected = value;
            RaisePropertyChanged("IsSelected");
        }
    }
    public bool IsEnabled
    {
        get { return offering.IsEnabled; }
        set
        {
            offering.IsEnabled = value;
            RaisePropertyChanged("IsEnabled");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
4

1 回答 1

5

这是个有趣的问题。由于您想要的操作适用于列表中的所有项目,因此此逻辑应处于列表类级别。您的 MyViewModel 课程很好。您需要在列表类和 XAML 中添加一些逻辑,但感谢 Prism,这很容易。

列表类(未在您的帖子中显示)包含:

    public ObservableCollection<MyViewModel> MyItems { get; set; } //Binding to ItemsSource

    private ICommand _selectCommand;

    public ICommand SelectCommand
    {
        get { return _selectCommand ?? (_selectCommand = new DelegateCommand<MyViewModel>(DoSelect)); }
    }

    private void DoSelect(MyViewModel myViewModel)
    {
        foreach(var item in MyItems)
            if (item != myViewModel)
            {
                item.IsSelected = false;
                item.IsEnabled = false;
            }
    }

    private ICommand _unselectCommand;

    public ICommand UnselectCommand
    {
        get { return _unselectCommand ?? (_unselectCommand = new DelegateCommand<MyViewModel>(DoUnselect)); }
    }

    private void DoUnselect(MyViewModel myViewModel)
    {
        foreach (var item in MyItems)
            if (item != myViewModel)
            {
                item.IsEnabled = true;
            }
    }

有两个命令,一个用于选择,另一个用于取消选择。神奇在于 XAML:

      <ListView ItemsSource="{Binding Path=MyItems}" x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding Path=IsSelected}" IsEnabled="{Binding Path=IsEnabled}">
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="Checked">
                                <i:InvokeCommandAction Command="{Binding ElementName=listView, Path=DataContext.SelectCommand}"
                                                       CommandParameter="{Binding}"/>
                            </i:EventTrigger>
                            <i:EventTrigger EventName="Unchecked">
                                <i:InvokeCommandAction Command="{Binding ElementName=listView, Path=DataContext.UnselectCommand}"
                                                       CommandParameter="{Binding}"/>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </CheckBox>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

使用 Prism 的触发器,您可以将 CheckBox 的 Checked 和 Unchecked 事件映射到列表视图模型的命令,并将项目视图模型作为参数传递。

它工作得很好,但有一点很烦人,设置项目的 IsSelected 是分开的。当您检查 CheckBox 时,后面的项目通过 DataBinding 设置为 true,但所有其他项目都通过父视图模型设置。如果您的帖子是您的全部要求,您可以删除 IsChecked 绑定并将设置一个 IsSelected 的逻辑放在列表视图模型中,这样看起来更清晰,更容易编写测试代码。

于 2013-07-31T18:21:08.040 回答