我在DataGridTemplateColumn中有一个ContextMenu,menuitems是视图的所有生产国家。我用它来过滤掉国家。
这是代码:
<DataGridTemplateColumn SortMemberPath="ProductionCountry" x:Name="prodCountryColumn" Width="Auto" CanUserSort="True">
<DataGridTemplateColumn.Header>
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock.ContextMenu x:Name="cmProdCountry" >
<ContextMenu Loaded="ContextMenu_Loaded" ItemsSource="{Binding Path=FilterProdCountry}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Name="prodCountryFilter" IsCheckable="True" Checked="toggleFilterOn" Unchecked="toggleFilterOff" Header="{Binding}" ItemsSource="{Binding}">
</MenuItem>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</TextBlock.ContextMenu>
Produksjonsland
</TextBlock>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Padding="5,1,5,1" Text="{Binding Path=ProductionCountry}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
要删除所有过滤,我有一个名为“全部显示”的商家信息。
菜单项是可检查的,这是我的问题:当菜单项“全部显示”被选中时,如何查找和取消选中所有菜单项。
在后面的代码中,我使用getancestor函数将我带到ContextMenu,但所有项目仅列为字符串,因此我无法设置MenuItem.IsChecked = false;
因此,当我尝试在代码隐藏中找到所有菜单项以取消选中时,我得到了异常。
这是代码:
var filterItem = (sender as MenuItem);
var parent = filterItem.FindAncestorTest<TextBlock>();
foreach (var menuitem in parent.Items)
{
(mi as MenuItem).IsChecked = false;
}
答案 0 :(得分:0)
首先,我想建议你避免使用混合的MVVM和代码隐藏。您应该选择其中一个并在项目的每个部分中使用它。
我个人更喜欢MVVM,所以我的解决方案符合MVVM。我不知道你所写的所有代码,所以我的答案基于一个简化的例子。
我刚刚为你称之为“过滤器”的对象创建了一个模型(每个过滤器由一个菜单项表示):
public class Filter : NotifyPropertyChangedBase
{
private bool isSelected;
private string description;
public Filter(string description)
{
this.description = description;
}
public string Description
{
get
{
return description;
}
set
{
if (StringComparer.Ordinal.Compare(description, value) != 0)
{
description = value;
OnPropertyChanged("Description");
}
}
}
public bool IsSelected
{
get
{
return isSelected;
}
set
{
if (isSelected != value)
{
isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
}
其中NotifyPropertyChangedBase
是一个只实现INotifyPropertyChanged的基类。
现在我的XAML:
<TextBox Margin="5" HorizontalAlignment="Stretch">
<TextBox.ContextMenu>
<ContextMenu ItemsSource="{Binding Path=FilterProdCountry}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<CheckBox Margin="4" HorizontalAlignment="Left"
VerticalAlignment="Center"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"
Content="{Binding Path=Description, Mode=OneWay}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
我们假设FilterProdCountry
是Filter
个对象的集合,属于您的ViewModel。那么......你想取消选中一个MenuItem吗?好吧,只需检索相关的Filter
对象,然后将其IsSelected
属性设置为false;例如:
if (vm.FilterProdCountry[0].IsSelected)
{
foreach (Filter filter in vm.FilterProdCountry.Skip(1))
{
filter.IsSelected = false;
}
}
其中vm
是ViewModel的实例。
我希望我的回答可以为你提供一个关于你的项目方式的提示。
答案 1 :(得分:0)
首先,我想在我的Xaml中指出一个错误,我将MenuItem放在ContextMenu.ItemTemplate中,它给了我两个MenuItem元素。为了获得我想要的所有复选框元素,我在此帖子中包含了Extention函数:How can I find WPF controls by name or type?。 并使用FindAllChildren函数,如下所示:
private void toggleFilterOn(object sender, RoutedEventArgs e)
{
var filterItem = (sender as CheckBox);
var parent = filterItem.FindAncestorOfType<ContextMenu>();
var children = parent.FindAllChildren().Where(item => item is CheckBox);
foreach (CheckBox cb in children)
{
cb.IsChecked = false;
}
}