我创建了一个简单的示例,它通过更大的用户控件 - 应用程序交互来复制我遇到的问题。控件已更改为简化,但反映了确切的问题。
我有一个用户控件(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。问题似乎是窗口中的绑定而不是用户控件,我已经破坏了我的大脑试图找出原因。
答案 0 :(得分:0)
这是因为您的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。