我想要一个通用的UserControl,在其中可以通过直接在XAML中设置其值或将其绑定到某些模型属性来设置属性。
就像TextBlock的Text属性一样。
现在,我只拥有简单的简单UserControl,它具有单个DependencyProperty TxT和绑定到其上的TextBlock Text属性。没有其他代码。
如果我在主窗口的XAML中设置了TxT,它将无法正常工作,则绑定有效。
如果我将PropertyChangedCallback添加到该DependencyProperty,它也可以在XAML中使用。
所以问题是,如果我希望能够直接在XAML中设置每个属性,是否必须对每个属性都设置PropertyChangedCallback?
这对我来说还不清楚,大多数都没有提及,但这也迫使我添加内部控件名称来更改它们在PropertyChangedCallback中的值。
代码在下面。
可以通过其他方式完成吗?
MainWindow
<Window
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:WpfAppDpBare" xmlns:Model="clr-namespace:WpfAppDpBare.Model" x:Class="WpfAppDpBare.MainWindow"
Background="CadetBlue"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Window.DataContext>
<Model:MainModel/>
</Window.DataContext>
<Grid>
<local:UserControlSample TxT="DIRECT TXT" HorizontalAlignment="Center" VerticalAlignment="Center" Height="125" Width="125" Margin="10,34,659,262"/>
<TextBlock HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Direct" VerticalAlignment="Top" FontSize="14" FontWeight="Bold"/>
<TextBlock HorizontalAlignment="Left" Margin="203,10,0,0" TextWrapping="Wrap" Text="Binding" VerticalAlignment="Top" FontSize="14" FontWeight="Bold"/>
<local:UserControlSample DataContext="{Binding UCData}" HorizontalAlignment="Center" VerticalAlignment="Center" Height="125" Width="125" Margin="203,34,466,262"/>
</Grid>
public partial class MainWindow:Window {
public MainWindow() {
InitializeComponent();
}
}
UserControl
<UserControl x:Class="WpfAppDpBare.UserControlSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfAppDpBare"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Background="White">
<Grid>
<TextBlock TextWrapping="Wrap" Text="{Binding TxT,FallbackValue=...,TargetNullValue=...}" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20" FontWeight="Bold"/>
</Grid>
public partial class UserControlSample:UserControl {
public UserControlSample() {
InitializeComponent();
}
public string TxT {
get { return (string)GetValue(TxTProperty); }
set { SetValue(TxTProperty, value); }
}
// Using a DependencyProperty as the backing store for TxT. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TxTProperty =
DependencyProperty.Register("TxT", typeof(string), typeof(UserControlSample), new PropertyMetadata());
}
模型
public class MainModel:ViewModelBase {
/// <summary>
/// The <see cref="UCData" /> property's name.
/// </summary>
public const string UCDataPropertyName = "UCData";
private UCModel uCModel = null;
/// <summary>
/// Sets and gets the UCData property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public UCModel UCData {
get {
return uCModel;
}
set {
if(uCModel == value) {
return;
}
uCModel = value;
RaisePropertyChanged(UCDataPropertyName);
}
}
public MainModel() {
UCData = new UCModel() { TxT = "BINDING TXT" };
}
}
public class UCModel:ViewModelBase {
/// <summary>
/// The <see cref="TxT" /> property's name.
/// </summary>
public const string TxTPropertyName = "TxT";
private string _TxT = null;
/// <summary>
/// Sets and gets the TxT property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public string TxT {
get {
return _TxT;
}
set {
if(_TxT == value) {
return;
}
_TxT = value;
RaisePropertyChanged(TxTPropertyName);
}
}
}
完整的裸项目https://wetransfer.com/downloads/199f3db5d183e64cf9f20db4225d4c9820180702001102/f4f61b
如您在项目绑定工程中所看到的,直接属性文本不是。
我希望所有这些内容都包含在usercontrol中,所以我可以在xaml中设置usercontrol属性值或将其绑定到主窗口xaml或代码中,而无需另外添加。
答案 0 :(得分:0)
您没有将TextBlock的Text
属性绑定到UserControl的TxT
属性。
设置绑定的RelativeSource
<TextBlock Text="{Binding TxT,
RelativeSource={RelativeSource AncestorType=UserControl}, ...}" .../>
或将x:Name
分配给UserControl并使用ElementName绑定。
然后,而不是通过以下方式设置UserControl的DataContext:
<local:UserControlSample DataContext="{Binding UCData}" .../>
绑定其TxT属性:
<local:UserControlSample TxT="{Binding UCData.TxT}" .../>
编辑:为了直接绑定到对象在其DataContext中的属性,
<local:UserControlSample DataContext="{Binding UCData}" .../>
您根本不需要在UserControl中声明任何属性。删除TxT依赖项属性声明,并直接绑定UserControl的XAML中的元素,就像已经做的那样:
<TextBlock Text="{Binding TxT, ...}"/>
但是请注意,这不是UserControl通常的工作方式。现在,您的确依赖于特定的视图模型类型,并且不能与其他视图模型一起使用。