WPF - 自定义控件的依赖项 属性 在 2 路模式下丢失绑定
WPF - Dependency Property of Custom Control lost Binding at 2 way mode
我有这个自定义控件
XAML:
<UserControl x:Class="WpfApplication1.UC"
...
x:Name="uc">
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<TextBox Text="{Binding Test, ElementName=uc}" Width="50" HorizontalAlignment="Left"/>
</StackPanel>
</UserControl>
C#
public partial class UC : UserControl
{
public static readonly DependencyProperty TestProperty;
public string Test
{
get
{
return (string)GetValue(TestProperty);
}
set
{
SetValue(TestProperty, value);
}
}
static UC()
{
TestProperty = DependencyProperty.Register("Test",typeof(string),
typeof(UC), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
}
public UC()
{
InitializeComponent();
}
}
这就是我使用自定义控件的方式:
<DockPanel>
<ItemsControl ItemsSource="{Binding Path=DataList}"
DockPanel.Dock="Left">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}" CommandParameter="{Binding}" Click="Button_Click"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<local:UC Test="{Binding SelectedString, Mode=OneWay}"/>
</DockPanel>
--
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private ObservableCollection<string> _dataList;
public ObservableCollection<string> DataList
{
get { return _dataList; }
set
{
_dataList = value;
OnPropertyChanged("DataList");
}
}
private string _selectedString;
public string SelectedString
{
get { return _selectedString; }
set
{
_selectedString = value;
OnPropertyChanged("SelectedString");
}
}
public MainWindow()
{
InitializeComponent();
this.DataList = new ObservableCollection<string>();
this.DataList.Add("1111");
this.DataList.Add("2222");
this.DataList.Add("3333");
this.DataList.Add("4444");
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.SelectedString = (sender as Button).CommandParameter.ToString();
}
}
如果我不更改 UC
的文本,一切正常。当我单击左侧面板中的每个按钮时,按钮的内容显示在 UC
.
但是当我更改 UC
的文本(例如:更改为 9999)时,Test
属性 失去了绑定。当我单击左侧面板中的每个按钮时,UC
的文本与更改后的文本相同 (9999)。在调试中,我看到 SelectedString
会因每次单击按钮而改变,但 UC 的文本不会。
我可以 'fix' 这个问题,方法是在 UC
中使用这个 <TextBox Text="{Binding Test, ElementName=uc, Mode=OneWay}" Width="50" HorizontalAlignment="Left"/>
。
但是我只是想弄明白问题所在,请问有人能帮我解释一下吗
设置单向绑定的目标值会清除绑定。绑定 <TextBox Text="{Binding Test, ElementName=uc}"
是双向的,当文本更改时它也会更新测试 属性。但是测试 属性 是单向绑定的目标,并且该绑定已被清除。
您的 'fix' 之所以有效,是因为作为单向绑定,它从不更新测试并且从不清除绑定。根据您的需要,您还可以将 UC 绑定更改为 <local:UC Test="{Binding SelectedString, Mode=TwoWay}"/>
当通过其他方法更新源或目标时,不会清除双向绑定。
下一行有问题
<local:UC Test="{Binding SelectedString, Mode=OneWay}"/>
模式设置为 SelectString
绑定的单向模式,因此当代码库中的值发生变化时,文本将被更新。更改源 属性 或目标 属性 以自动将绑定源更新为 TwoWay
。
<local:UC Test="{Binding SelectedString, Mode=TwoWay}"/>
我有这个自定义控件
XAML:
<UserControl x:Class="WpfApplication1.UC"
...
x:Name="uc">
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<TextBox Text="{Binding Test, ElementName=uc}" Width="50" HorizontalAlignment="Left"/>
</StackPanel>
</UserControl>
C#
public partial class UC : UserControl
{
public static readonly DependencyProperty TestProperty;
public string Test
{
get
{
return (string)GetValue(TestProperty);
}
set
{
SetValue(TestProperty, value);
}
}
static UC()
{
TestProperty = DependencyProperty.Register("Test",typeof(string),
typeof(UC), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
}
public UC()
{
InitializeComponent();
}
}
这就是我使用自定义控件的方式:
<DockPanel>
<ItemsControl ItemsSource="{Binding Path=DataList}"
DockPanel.Dock="Left">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding}" CommandParameter="{Binding}" Click="Button_Click"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<local:UC Test="{Binding SelectedString, Mode=OneWay}"/>
</DockPanel>
--
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private ObservableCollection<string> _dataList;
public ObservableCollection<string> DataList
{
get { return _dataList; }
set
{
_dataList = value;
OnPropertyChanged("DataList");
}
}
private string _selectedString;
public string SelectedString
{
get { return _selectedString; }
set
{
_selectedString = value;
OnPropertyChanged("SelectedString");
}
}
public MainWindow()
{
InitializeComponent();
this.DataList = new ObservableCollection<string>();
this.DataList.Add("1111");
this.DataList.Add("2222");
this.DataList.Add("3333");
this.DataList.Add("4444");
this.DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.SelectedString = (sender as Button).CommandParameter.ToString();
}
}
如果我不更改 UC
的文本,一切正常。当我单击左侧面板中的每个按钮时,按钮的内容显示在 UC
.
但是当我更改 UC
的文本(例如:更改为 9999)时,Test
属性 失去了绑定。当我单击左侧面板中的每个按钮时,UC
的文本与更改后的文本相同 (9999)。在调试中,我看到 SelectedString
会因每次单击按钮而改变,但 UC 的文本不会。
我可以 'fix' 这个问题,方法是在 UC
中使用这个 <TextBox Text="{Binding Test, ElementName=uc, Mode=OneWay}" Width="50" HorizontalAlignment="Left"/>
。
但是我只是想弄明白问题所在,请问有人能帮我解释一下吗
设置单向绑定的目标值会清除绑定。绑定 <TextBox Text="{Binding Test, ElementName=uc}"
是双向的,当文本更改时它也会更新测试 属性。但是测试 属性 是单向绑定的目标,并且该绑定已被清除。
您的 'fix' 之所以有效,是因为作为单向绑定,它从不更新测试并且从不清除绑定。根据您的需要,您还可以将 UC 绑定更改为 <local:UC Test="{Binding SelectedString, Mode=TwoWay}"/>
当通过其他方法更新源或目标时,不会清除双向绑定。
下一行有问题
<local:UC Test="{Binding SelectedString, Mode=OneWay}"/>
模式设置为 SelectString
绑定的单向模式,因此当代码库中的值发生变化时,文本将被更新。更改源 属性 或目标 属性 以自动将绑定源更新为 TwoWay
。
<local:UC Test="{Binding SelectedString, Mode=TwoWay}"/>