尝试将一个复选框列表框分组,并生成一个';全选';按钮
本文关键字:一个 全选 按钮 复选框 列表 | 更新日期: 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类型开始,然后在逻辑完成后将区域类型设置为临时列表中的值。如果你有问题,请告诉我。