如何重用WPF用户控件,但更改绑定属性?
问题描述:
我有一个WPF用户控件,它使用我的viewmodel中的一个属性进行绑定。我现在想用相同viewmodel使用该用户控件的两个实例,但重写其中一个的绑定。如何重用WPF用户控件,但更改绑定属性?
的代码看起来是这样的
用户控制
<UserControl x:Class="TestWpfApp.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestWpfApp">
<Grid>
<DockPanel>
<Label Margin="10" Content="{Binding MyLabel}"/>
<Button Margin="10" Content="{Binding MyButton}"/>
</DockPanel>
</Grid>
</UserControl>
主视图
<Window x:Class="TestWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestWpfApp"
Title="MainWindow" Height="150" Width="525">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<DockPanel>
<local:UserControl1 DockPanel.Dock="Top" x:Name="UserControl1"/>
<!--In this instance of UserControl1, I want the Label to bind to the MyNewLabel-->
<local:UserControl1 DockPanel.Dock="Top" x:Name="UserControl2"/>
</DockPanel>
</Grid>
</Window>
视图模型
public class ViewModel
{
public string MyLabel => "Label1";
public string MyButton => "Button1";
public string MyNewLabel => "Label2";
}
在第二个实例,我想将标签绑定到不同的属性。我尝试将该属性设置为用户控件上的资源,然后在主视图中覆盖它,但我无法使其工作。
实际上,我使用DevExpress控件和POCO视图模型,如果这样做更容易。
答
创建自定义控件时 - 将自定义控件内的控件绑定到由外部数据上下文提供的任意属性不是一个好主意。不仅你正在得到像现在这样的问题,那个控件的用户不知道哪个datacontext应该提供哪个属性来控制它的工作。只查看UserControl的源代码可能会发现它需要具有属性MyLabel
和MyButton
的数据上下文。相反 - 使控制自足通过控制自身引入的依赖属性:
public partial class UserControl1 : UserControl {
public UserControl1() {
InitializeComponent();
}
public string Text
{
get { return (string) GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(UserControl1), new PropertyMetadata(null));
public string ButtonText
{
get { return (string) GetValue(ButtonTextProperty); }
set { SetValue(ButtonTextProperty, value); }
}
public static readonly DependencyProperty ButtonTextProperty =
DependencyProperty.Register("ButtonText", typeof(string), typeof(UserControl1), new PropertyMetadata(null));
}
并绑定到这些属性:
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="self">
<Grid>
<DockPanel>
<Label Margin="10"
Content="{Binding Text, ElementName=self}" />
<Button Margin="10"
Content="{Binding ButtonText, ElementName=self}" />
</DockPanel>
</Grid>
</UserControl>
然后在主窗口 - 绑定那些依赖属性到你的模型:
<Window.DataContext>
<my:ViewModel />
</Window.DataContext>
<Grid>
<DockPanel>
<my:UserControl1 DockPanel.Dock="Top"
x:Name="UserControl1" Text="{Binding MyLabel}" ButtonText="{Binding MyButton}" />
<!--In this instance of UserControl1, I want the Label to bind to the MyNewLabel-->
<my:UserControl1 DockPanel.Dock="Top"
x:Name="UserControl2"
Text="{Binding MyNewLabel}"
ButtonText="{Binding MyButton}" />
</DockPanel>
</Grid>