如何使用 ViewModel 为 UserControl 设置数据绑定
How to set DataBinding for UserControl with ViewModel
我有一个用户控件,里面有几个控件。所以我决定使用 ViewModel 来管理所有这些可绑定的值。但我发现我的绑定始终为空。那么如何在 usercontrol
中为 ViewModel 设置绑定
MainWindows.xaml
<Window x:Class="Test.MainWindow"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<cus:Wizard WizardModel="{Binding MyModel}"/>
</StackPanel>
</Window>
MainWindows.xaml.cs
public partial class MainWindow : Window
{
private ViewModel vm = new ViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = vm;
}
}
ViewModel.cs(主窗口视图模型)
public class ViewModel : INotifyPropertyChanged
{
private Model _MyModel;
public Model MyModel
{
get
{
return _MyModel;
}
set
{
_MyModel = value;
NotifyPropertyChanged("MyModel");
}
}
}
Wizard.xaml(我的用户控件)
<UserControl mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Something}" />
</Grid>
</UserControl>
Wizard.xaml.cs
public partial class Wizard : UserControl
{
private readonly object modelLock = new object();
private Model CurrentModel = new Model();
public Wizard()
{
InitializeComponent();
DataContext = CurrentModel;
}
public Model WizardModel
{
get { return (Model)this.GetValue(WizardModelProperty); }
set { this.SetValue(WizardModelProperty, value); }
}
public static readonly DependencyProperty WizardModelProperty = DependencyProperty.Register("WizardModel", typeof(Model), typeof(Wizard), new PropertyMetadata(null, new PropertyChangedCallback(ModelChanged)));
private static void ModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Wizard)d).OnModelChanged();
}
private void OnModelChanged()
{
lock (this.modelLock)
{
if(CurrentModel != null)
{
CurrentModel = null;
}
if (WizardModel != null)
{
CurrentModel = WizardModel;
}
}
}
}
UserControl 中的 WizardModel 始终为空。那么如何在 UserControl
中设置这个 ViewModel
应该在特定视图模型 class 上运行的 UserControl - 或者更准确地说在具有一组特定 public 属性的 class 上运行 - 可以直接绑定到在其 XAML.
中查看模型属性
给定一个像
这样的视图模型
public class Model
{
public string Something { get; set; }
}
你可以只写一个 UserControl XAML
<UserControl ...>
...
<TextBox Text="{Binding Something}" />
...
</UserControl>
和后面的这段代码
public partial class Wizard : UserControl
{
public Wizard()
{
InitializeComponent();
}
}
如果您现在将其 DataContext 设置为 Model
的实例(或任何其他带有 Something
属性 的 class 实例),它将正常工作:
<local:Wizard DataContext="{Binding MyModel}"/>
由于 DataContext 属性 的值从父元素继承到子元素,因此这也有效:
<StackPanel DataContext="{Binding MyModel}">
<local:Wizard/>
</StackPanel>
但是,UserControl 仍然依赖于其 DataContext 中 Something
属性 的存在。为了摆脱这种依赖,你的控件可能会暴露一个依赖属性
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register(nameof(MyText), typeof(string), typeof(Wizard));
public string MyText
{
get { return (string)GetValue(MyTextProperty); }
set { SetValue(MyTextProperty, value); }
}
并将其 XAML 中的元素绑定到它自己的 属性
<UserControl ...>
...
<TextBox Text="{Binding MyText,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
...
</UserControl>
现在您将绑定控件的 属性 而不是设置其 DataContext:
<local:Wizard MyText="{Binding MyModel.Something, Mode=TwoWay}"/>
我有一个用户控件,里面有几个控件。所以我决定使用 ViewModel 来管理所有这些可绑定的值。但我发现我的绑定始终为空。那么如何在 usercontrol
中为 ViewModel 设置绑定MainWindows.xaml
<Window x:Class="Test.MainWindow"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<cus:Wizard WizardModel="{Binding MyModel}"/>
</StackPanel>
</Window>
MainWindows.xaml.cs
public partial class MainWindow : Window
{
private ViewModel vm = new ViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = vm;
}
}
ViewModel.cs(主窗口视图模型)
public class ViewModel : INotifyPropertyChanged
{
private Model _MyModel;
public Model MyModel
{
get
{
return _MyModel;
}
set
{
_MyModel = value;
NotifyPropertyChanged("MyModel");
}
}
}
Wizard.xaml(我的用户控件)
<UserControl mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Something}" />
</Grid>
</UserControl>
Wizard.xaml.cs
public partial class Wizard : UserControl
{
private readonly object modelLock = new object();
private Model CurrentModel = new Model();
public Wizard()
{
InitializeComponent();
DataContext = CurrentModel;
}
public Model WizardModel
{
get { return (Model)this.GetValue(WizardModelProperty); }
set { this.SetValue(WizardModelProperty, value); }
}
public static readonly DependencyProperty WizardModelProperty = DependencyProperty.Register("WizardModel", typeof(Model), typeof(Wizard), new PropertyMetadata(null, new PropertyChangedCallback(ModelChanged)));
private static void ModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Wizard)d).OnModelChanged();
}
private void OnModelChanged()
{
lock (this.modelLock)
{
if(CurrentModel != null)
{
CurrentModel = null;
}
if (WizardModel != null)
{
CurrentModel = WizardModel;
}
}
}
}
UserControl 中的 WizardModel 始终为空。那么如何在 UserControl
中设置这个 ViewModel应该在特定视图模型 class 上运行的 UserControl - 或者更准确地说在具有一组特定 public 属性的 class 上运行 - 可以直接绑定到在其 XAML.
中查看模型属性给定一个像
这样的视图模型public class Model
{
public string Something { get; set; }
}
你可以只写一个 UserControl XAML
<UserControl ...>
...
<TextBox Text="{Binding Something}" />
...
</UserControl>
和后面的这段代码
public partial class Wizard : UserControl
{
public Wizard()
{
InitializeComponent();
}
}
如果您现在将其 DataContext 设置为 Model
的实例(或任何其他带有 Something
属性 的 class 实例),它将正常工作:
<local:Wizard DataContext="{Binding MyModel}"/>
由于 DataContext 属性 的值从父元素继承到子元素,因此这也有效:
<StackPanel DataContext="{Binding MyModel}">
<local:Wizard/>
</StackPanel>
但是,UserControl 仍然依赖于其 DataContext 中 Something
属性 的存在。为了摆脱这种依赖,你的控件可能会暴露一个依赖属性
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register(nameof(MyText), typeof(string), typeof(Wizard));
public string MyText
{
get { return (string)GetValue(MyTextProperty); }
set { SetValue(MyTextProperty, value); }
}
并将其 XAML 中的元素绑定到它自己的 属性
<UserControl ...>
...
<TextBox Text="{Binding MyText,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
...
</UserControl>
现在您将绑定控件的 属性 而不是设置其 DataContext:
<local:Wizard MyText="{Binding MyModel.Something, Mode=TwoWay}"/>