尝试将一个复选框列表框分组,并生成一个';全选';按钮

本文关键字:一个 全选 按钮 复选框 列表 | 更新日期: 2024-10-20 17:58:44

我正试图在WPF应用程序中创建一个搜索菜单。因此,我在4个不同的列表框中自然有一堆不同的搜索条件。我很难配置"全选"复选框来取消选中列表框中的所有其他复选框。

以下是其中一个列表框的示例:

    <StackPanel x:Name="RegionSelection" Orientation="Vertical" Grid.Row="0" Grid.Column="4">
        <TextBlock Style="{DynamicResource LabelTextblockStyle}"
       VerticalAlignment="top" HorizontalAlignment="Left" 
               Margin="4,4,4,4">Regions:</TextBlock>
        <StackPanel Orientation="Vertical" HorizontalAlignment="Left">
            <ListBox  Margin="4,0" HorizontalAlignment="Left" ItemsSource="{Binding Path=RegionTypes, Mode=TwoWay}" ItemContainerStyle="{DynamicResource NoHighlightList}">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <UniformGrid Columns="2"/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                            <CheckBox Content="{Binding Path=RegionDesc}" Command="{Binding Path=UncheckAllCommand}" Margin="4" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>
    </StackPanel>

这是ViewModel:

     private List<SearchRegion> _regionTypes;
    public List<SearchRegion> RegionTypes
    {
        get { return _regionTypes; }
        set
        {
            _regionTypes = value;
            RaisePropertyChanged();
        }
    }
    RegionTypes = new List<SearchRegion>
        {   new SearchRegion {RegionDesc = "All Regions"},
            new SearchRegion {RegionDesc = "Region 4", Region="4"},
            new SearchRegion {RegionDesc = "Region 1", Region="1"},
            new SearchRegion {RegionDesc = "Region 5", Region="5"},
            new SearchRegion {RegionDesc = "Region 2", Region="2"},
            new SearchRegion {RegionDesc = "Region 6", Region="6"},
            new SearchRegion {RegionDesc = "Region 3", Region="3"}
        };

和命令:

    UncheckAllCommand = new RelayCommand(UncheckAll);
    public ICommand UncheckAllCommand {get; private set;}
     private void UncheckAll()
    {
        if(RegionTypes.Any((x) => x.RegionDesc.ToUpper().Equals("ALL REGIONS") && x.IsChecked))
        {
            RegionTypes.ForEach((x) => x.IsChecked = x.RegionDesc.ToUpper() != "ALL REGIONS" ? false : true);
        }
    }

不幸的是,它并没有取消选中ListBox的其余部分。如有任何帮助,我们将不胜感激。

编辑:我忘记添加保存SearchRegion属性的类。这是:

    public class SearchRegion : BaseModel
{
        public SearchRegion() { }

        public string RegionDesc { get; set; }
    public string Region { get; set; }
    bool _isChecked = false;
    public bool IsChecked
    {
        get { return _isChecked; }
        set
        {
            _isChecked = value;
        }
    }

}

尝试将一个复选框列表框分组,并生成一个';全选';按钮

在您的代码中,我发现了2个问题。

1) 您的模型应该实现INotifyPropertyChanged接口:

public class SearchRegion : INotifyPropertyChanged
{
    public SearchRegion() { }
    public string RegionDesc { get; set; }
    public string Region { get; set; }
    bool _isChecked = false;
    public bool IsChecked
    {
        get { return _isChecked; }
        set
        {
            _isChecked = value;
            OnPropertyChanged("IsChecked");
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }
}

2) 如果命令UncheckAllCommand在ViewModel中,那么绑定应该如下所示:

...
<ListBox.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
            <CheckBox Content="{Binding Path=RegionDesc}" 
                      Command="{Binding Path=DataContext.UncheckAllCommand, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBox}}" 
                      Margin="4" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}"/>
        </StackPanel>
    </DataTemplate>
</ListBox.ItemTemplate>
...

如果你写这样的东西:

...
<ListBox.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
            <CheckBox Content="{Binding Path=RegionDesc}" 
            Command="{Binding Path=UncheckAllCommand}" 
            Margin="4" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}"/>
        </StackPanel>
    </DataTemplate>
</ListBox.ItemTemplate>
...

您希望UncheckAllCommand是在模型类中声明的(在您的情况下,它是SearchRegion类)。

在回答我自己的问题时,这就是我解决问题的方法。请记住,有很多方法可以做我想做的事情,但这就是我跌跌撞撞地完成它的方法。

在我看来,我不需要命令,因为我创建了一个被操纵的临时列表,然后通知视图。因此,以下是观点:

    <StackPanel x:Name="RegionSelection" Orientation="Vertical" Grid.Row="0" Grid.Column="4">
        <TextBlock Style="{DynamicResource LabelTextblockStyle}"
       VerticalAlignment="top" HorizontalAlignment="Left" 
               Margin="4,4,4,4">Regions:</TextBlock>
        <StackPanel Orientation="Vertical" HorizontalAlignment="Left">
           <ListBox  Margin="4,0" HorizontalAlignment="Left" ItemsSource="{Binding Path=RegionTypes, Mode=TwoWay}" ItemContainerStyle="{DynamicResource NoHighlightList}">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <UniformGrid Columns="2"/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                            <CheckBox Content="{Binding Path=RegionDesc}"  Margin="4" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" IsEnabled="{Binding Path=IsEnabled, Mode=TwoWay}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>
    </StackPanel>

在ViewModel中,我不得不将"List"替换为"ObservableCollection",所以这里是我的位置:

         private ObservableCollection<SearchRegion> _regionTypes;
    public ObservableCollection<SearchRegion> RegionTypes
    {
        get { return _regionTypes; }
        set
        {
            _regionTypes = value;
            RaisePropertyChanged();
        }
    }
    RegionTypes = new ObservableCollection<SearchRegion>
        {   new SearchRegion {RegionDesc = "All Regions"},
            new SearchRegion {RegionDesc = "Region 4", Region="4"},
            new SearchRegion {RegionDesc = "Region 1", Region="1"},
            new SearchRegion {RegionDesc = "Region 5", Region="5"},
            new SearchRegion {RegionDesc = "Region 2", Region="2"},
            new SearchRegion {RegionDesc = "Region 6", Region="6"},
            new SearchRegion {RegionDesc = "Region 3", Region="3"}
        };

然后,我创建了一些逻辑作为事件,这使我只能在选中"所有区域"复选框时运行逻辑。

     foreach(var region in RegionTypes.Where((x) => x.RegionDesc.ToUpper().Equals("ALL REGIONS")))
            region.PropertyChanged += UncheckAll;

以下是更改非"所有区域"复选框状态的逻辑

     if (RegionTypes.Any((x) => x.RegionDesc.ToUpper().Equals("ALL REGIONS") && x.IsChecked))
        {
            foreach (var region in tempRegions.Where((x) => !x.RegionDesc.ToUpper().Equals("ALL REGIONS")))
                region.IsChecked = true;
    }
        RegionTypes = new ObservableCollection<SearchRegion>();
        RegionTypes = tempRegions;

就是这样。我创建了临时列表,从Region类型开始,然后在逻辑完成后将区域类型设置为临时列表中的值。如果你有问题,请告诉我。