试图让CheckBoxes的ListBox分组,然后选择All All'按钮

时间:2016-04-19 14:29:58

标签: c# wpf xaml checkbox listbox

我正在尝试在WPF应用程序中创建搜索菜单。所以,我自然而然地在4个不同的ListBox中有一堆不同的搜索条件。我很难配置一个'全选'复选框取消选中ListBox中的所有其他CheckBox。

以下是其中一个ListBox的示例:

    <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属性的Class。这是:

    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 个答案:

答案 0 :(得分:0)

在您的代码中,我发现了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类)。

答案 1 :(得分:0)

在回答我自己的问题时,我就是这样解决的。请记住,有很多方法可以做我想要的,但这是如何偶然发现它。

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

    <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中,我不得不交换&#39; List&#39; for&#39; ObservableCollection&#39;所以这就是我所拥有的:

         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;

以下是改变不是所有地区&#39;

的复选框状态的逻辑
     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;

这就是它。我创建了templist,从Region类型然后在逻辑完成后将区域类型设置为templist中的值。 如果您有疑问,请告诉我。