我使用CollectionView
将项目分组如下:
<CollectionViewSource Source="{Binding Competitions}" x:Key="GroupedData">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Item.Country" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
完整的XAML结构是这样的:
<ComboBox x:Name="CompetitionCombo"
ItemsSource="{Binding Source={StaticResource GroupedData}}"
ItemTemplate="{StaticResource CombinedTemplate}">
<ComboBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource containerStyle}"
HeaderTemplate="{StaticResource GroupHeader}">
</GroupStyle>
</ComboBox.GroupStyle>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource NormalItemTemplate}" />
</DataTemplate>
<DataTemplate x:Key="GroupHeader">
<DockPanel>
<Image Source="{Binding Name.ISO,
Converter={StaticResource CountryIdToFlagImageSourceConverter}}"
Stretch="None" Width="23" Height="18" RenderOptions.BitmapScalingMode="HighQuality" />
<TextBlock Text="{Binding Name.Name}" Margin="10,0,0,0" Foreground="Black" FontWeight="Bold"/>
<CheckBox Margin="5,0,0,0" HorizontalAlignment="Right" IsChecked="True" x:Name="PART_DisplayLeague"
Unchecked="CheckBoxCountry_Unchecked" Checked="CheckBoxCountry_Checked" />
</DockPanel>
</DataTemplate>
<Style TargetType="{x:Type GroupItem}" x:Key="containerStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="False" x:Name="ComboExpander"
Header="{TemplateBinding Content}"
HeaderTemplate="{StaticResource GroupHeader}" >
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
正如您在GroupHeader
我CheckBox
中看到的那样,我试图通过以下方式访问此CheckBox
:
//current value of league.Country = "England";
//Iterate the available groups
foreach(CollectionViewGroup gp in CompetitionCombo.Items.Groups)
{
if(league.Country.Name == (gp.Name as Country).Name)
{
//Get the container
GroupItem container = CompetitionCombo.ItemContainerGenerator.ContainerFromItem(gp) as GroupItem;
//Get the control
var control = container.Template.FindName("PART_DisplayLeague", container);
control.IsChecked = true;
}
}
我的组正确,但control
变量甚至是Null
,似乎代码找不到PART_DisplayLeague
:与标题中的Country
关联的CheckBox容器。
注意:
league
是以下内容的简单实现:
public class League
{
public string Name { get; set; }
public Country Country { get; set; }
}
public class Country
{
public string Name { get; set; }
public string ISO { get; set; }
}
我做错了什么?
更新
忘记添加集合实现,特别是Competition
:
public List<CheckedListItem<League>> Competitions = new List<CheckedListItem<League>>();
用于向集合中添加元素:
Competitions.Add(new CheckedListItem<League>
{
IsChecked = true,
Item = new League { Name = "foo" }
});
可以找到CheckedListItem
here
您可以看到Item
是CheckedListItem
的一部分。
更新#2
情况的实践例子:
假设Competitions
包含以下项目:
Competitions.Add(new CheckedListItem<League>
{
IsChecked = true,
Item = new League { Name = "foo", Country = new Country { Name = "Italy"}}
});
Competitions.Add(new CheckedListItem<League>
{
IsChecked = true,
Item = new League { Name = "foo2", Country = new Country { Name = "Italy"}}
});
Competitions.Add(new CheckedListItem<League>
{
IsChecked = true,
Item = new League { Name = "foo", Country = new Country { Name = "England"}}
});
UI结构将:
[] Italy <- this is the GroupHeader sort by xaml
[] foo <- Items of the container
[] foo2
[] England
[] foo3
现在我要求的是:当我检查foo2和foo时,Italy
CheckBox需要被检查,当我取消选中Italy
容器中包含的Item时,那么,{ {1}}必须取消选中。
这意味着两件事:
我的问题是我无法找到与国家/地区相关联的CheckBox是由Xaml生成的,这就是我无法使用Binding属性的原因如建议的那样。
答案 0 :(得分:2)
发布有人可以复制粘贴并重现问题的代码,然后人们不仅可以解决您的问题,还可以提出更好的解决方案。
在此期间,您可以通过以下方式找到您的复选框:
var control = FindVisualChildren<CheckBox>(container);
Here you can find the method FindVisualChildren
编辑:一个完整的工作示例
public class League
{
public string Name { get; set; }
public Country Country { get; set; }
}
public class Country
{
public string Name { get; set; }
public string ISO { get; set; }
}
public class CheckedListItem<T>
{
private bool isChecked;
private T item;
public CheckedListItem() { }
public CheckedListItem(T item, bool isChecked = false)
{
this.item = item;
this.isChecked = isChecked;
}
public T Item
{
get { return item; }
set
{
item = value;
}
}
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
}
}
}
public partial class MainWindow : Window
{
public ObservableCollection<CheckedListItem<League>> Competitions { get; set; }
public MainWindow()
{
InitializeComponent();
Competitions = new ObservableCollection<CheckedListItem<League>> { (new CheckedListItem<League>
{
IsChecked = true,
Item = new League { Name = "foo", Country = new Country { Name = "Italy" } }
}),
(new CheckedListItem<League>
{
IsChecked = true,
Item = new League { Name = "foo2", Country = new Country { Name = "Italy" } }
}),
(new CheckedListItem<League>
{
IsChecked = true,
Item = new League { Name = "foo", Country = new Country { Name = "England" } }
}) };
this.DataContext = this;
}
public void CheckBoxCountry_Checked(object sender, EventArgs args)
{
foreach (CollectionViewGroup gp in CompetitionCombo.Items.Groups)
{
//Get the container
GroupItem container = CompetitionCombo.ItemContainerGenerator.ContainerFromItem(gp) as GroupItem;
//Get the control
var control = FindVisualChildren<CheckBox>(container);
}
}
public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
yield return (T)child;
foreach (T childOfChild in FindVisualChildren<T>(child))
yield return childOfChild;
}
}
}
}
的.xaml
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<CollectionViewSource Source="{Binding Competitions}" x:Key="GroupedData">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Item.Country" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<DataTemplate x:Key="NormalItemTemplate">
<DockPanel>
<TextBlock Text="sdf" Margin="10,0,0,0" Foreground="Black" FontWeight="Bold"/>
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource NormalItemTemplate}"
/>
</DataTemplate>
<DataTemplate x:Key="GroupHeader">
<DockPanel>
<TextBlock Text="{Binding Name.Name}" Margin="10,0,0,0" Foreground="Black" FontWeight="Bold"/>
<CheckBox Margin="5,0,0,0" HorizontalAlignment="Right" IsChecked="True" x:Name="PART_DisplayLeague"
Checked="CheckBoxCountry_Checked" />
</DockPanel>
</DataTemplate>
<Style TargetType="{x:Type GroupItem}" x:Key="containerStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="False" x:Name="ComboExpander"
Header="{TemplateBinding Content}"
HeaderTemplate="{StaticResource GroupHeader}" >
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<ComboBox x:Name="CompetitionCombo"
ItemsSource="{Binding Source={StaticResource GroupedData}}"
ItemTemplate="{StaticResource CombinedTemplate}">
<ComboBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource containerStyle}"
HeaderTemplate="{StaticResource GroupHeader}">
</GroupStyle>
</ComboBox.GroupStyle>
</ComboBox>
</Grid>
</Window>
我添加了NormalItemTemplate
,因为您没有提供模板。
当您选中UI中的复选框时,您将在mainwindow.cs中调用CheckBoxCountry_Checked方法,该方法将在所有3个组合框中找到该复选框。