在WPF中的UserControl中的ItemsControl中绑定问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在WPF中的UserControl中的ItemsControl中绑定问题相关的知识,希望对你有一定的参考价值。
我创建了一个简单的示例,它通过更大的用户控件 - 应用程序交互来复制我遇到的问题。控件已更改为简化,但反映了确切的问题。
我有一个用户控件(CheckBoxTable),它根据属性CheckBoxData创建一个复选框网格:
<UserControl
x:Class="WPFNotWorkingTest.CheckBoxTable"
x:Name="CheckBoxTableName">
<ItemsControl DataContext="{Binding ElementName=CheckBoxTableName}" ItemsSource="{Binding CheckBoxData}">
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding GridRow}" />
<Setter Property="Grid.Column" Value="{Binding GridColumn}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid ShowGridLines="True" Style="{Binding Path=Style}" Loaded="OnGrid_Loaded"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsCheckBoxChecked}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
ItemSource CheckBoxData是CheckBoxTable用户控件中的ObservableCollection。
public ObservableCollection<CheckBoxTableData> CheckBoxData
{
get { return (ObservableCollection<CheckBoxTableData>)GetValue(CheckBoxDataProperty); }
set { SetValue(CheckBoxDataProperty, value); }
}
// Using a DependencyProperty as the backing store for CheckBoxData. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CheckBoxDataProperty =
DependencyProperty.Register("CheckBoxData", typeof(ObservableCollection<CheckBoxTableData>), typeof(CheckBoxTable), new PropertyMetadata(null, new PropertyChangedCallback(CheckBoxTable.OnCheckBoxData_Changed)));
private static void OnCheckBoxData_Changed(DependencyObject dObject, DependencyPropertyChangedEventArgs e)
{
CheckBoxTable table = (CheckBoxTable)dObject;
ObservableCollection<CheckBoxTableData> objOldValue = (ObservableCollection<CheckBoxTableData>)e.OldValue;
if (objOldValue != null)
{
objOldValue.CollectionChanged -= table.OnTableData_CollectionChanged;
}
ObservableCollection<CheckBoxTableData> objNewValue = (ObservableCollection<CheckBoxTableData>)e.NewValue;
if (objNewValue != null)
{
objNewValue.CollectionChanged += table.OnTableData_CollectionChanged;
}
}
CheckBoxTableData类
public class CheckBoxTableData : DependencyObject
{
public bool? IsCheckBoxChecked
{
get { return (bool?)GetValue(IsCheckBoxCheckedProperty); }
set { SetValue(IsCheckBoxCheckedProperty, value); }
}
// Using a DependencyProperty as the backing store for IsCheckBoxChecked. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsCheckBoxCheckedProperty =
DependencyProperty.Register("IsCheckBoxChecked", typeof(bool?), typeof(CheckBoxTableData), new PropertyMetadata(true));
public int GridRow
{
get { return (int)GetValue(GridRowProperty); }
set { SetValue(GridRowProperty, value); }
}
// Using a DependencyProperty as the backing store for GridRow. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridRowProperty =
DependencyProperty.Register("GridRow", typeof(int), typeof(CheckBoxTableData), new PropertyMetadata(0));
public int GridColumn
{
get { return (int)GetValue(GridColumnProperty); }
set { SetValue(GridColumnProperty, value); }
}
// Using a DependencyProperty as the backing store for GridColumn. This enables animation, styling, binding, etc...
public static readonly DependencyProperty GridColumnProperty =
DependencyProperty.Register("GridColumn", typeof(int), typeof(CheckBoxTableData), new PropertyMetadata(0));
}
}
在窗口中使用:
<Window x:Class="WPFNotWorkingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFNotWorkingTest"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Content="Click Me" Click="Button_Click" Margin="5"/>
<local:CheckBoxTable Grid.Row="1" CheckBoxPerRow="10">
<local:CheckBoxTable.CheckBoxData>
<local:CheckBoxTableData IsCheckBoxChecked="True"/>
<local:CheckBoxTableData IsCheckBoxChecked="False"/>
<local:CheckBoxTableData IsCheckBoxChecked="{Binding CheckMyBinding}"/>
</local:CheckBoxTable.CheckBoxData>
</local:CheckBoxTable>
</Grid>
</Window>
MainWindow.cs
public partial class MainWindow : Window
{
public bool? CheckMyBinding
{
get { return (bool?)GetValue(CheckMyBindingProperty); }
set { SetValue(CheckMyBindingProperty, value); }
}
// Using a DependencyProperty as the backing store for CheckMyBinding. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CheckMyBindingProperty =
DependencyProperty.Register("CheckMyBinding", typeof(bool?), typeof(MainWindow), new PropertyMetadata(false));
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (CheckMyBinding == true)
{
CheckMyBinding = false;
}
else
{
CheckMyBinding = true;
}
}
}
单击按钮并执行处理程序不会切换CheckBox的IsChecked。问题似乎是窗口中的绑定而不是用户控件,我已经破坏了我的大脑试图找出原因。
发生这种情况是因为你的CheckBoxTableData
无法知道你的MainWindow
。由CheckBoxTable
中的ItemsControl生成的CheckBoxes都有一个CheckBoxData
实例作为它们的DataSource。然而,CheckBoxTableData
没有自己的DataContext,你不能使用RelativeSource
,因为它们不是应用程序的可视或逻辑树的一部分。
XAML设计师可能会使它看起来像它的工作(显示自动完成和所有),但这只是因为它不知道你的控件是如何工作的。
您可以通过在代码中手动设置此绑定来解决此问题,如下所示:
CheckBoxTableData tableData = new CheckBoxTableData();
BindingOperations.SetBinding(tableData, CheckBoxTableData.IsCheckBoxCheckedProperty,
new Binding("CheckMyBinding") {Source = this}); // this = MainWindow
checkBoxTable.CheckBoxData = new ObservableCollection<CheckBoxTableData>();
checkBoxTable.CheckBoxData.Add(tableData);
但是,在ViewModel中处理此问题而不是将该属性添加到MainWindow会更加清晰。
以上是关于在WPF中的UserControl中的ItemsControl中绑定问题的主要内容,如果未能解决你的问题,请参考以下文章
在WPF中的UserControl中的ItemsControl中绑定问题
如何从 UserControl 访问 WPF 页面中的公共变量?
无法在WPF中创建继承的usercontrol,本地命名空间中的基本控件“不存在”
从 Catel WPF UserControl 中的 ResourceDictionary 中绑定