目前,在实际的应用程序开发中,我正在努力消耗MVVM模式中的自定义UserControl
。
在我的应用程序中,有一个DataGrid
,用户可以在其中选择一个条目。 DataGrid
的{{1}}为SelectedItem
- 绑定到ViewModel设置为TwoWay
的字段。当用户选择条目时,该字段被正确更新(测试)。在保存DataContext
的{{1}}中,字段通过XAML绑定到MVVM模式中设计的自定义Page
的{{1}}:它将自己的ViewModel裸露出来设为DataGrid
。问题是即使DependencyProperty
接口正确实现,当字段发生更改时UserControl
的{{1}}也不会更新(请参阅下一个最小工作示例中与传统控件的比较) )。
此示例由DataContext
和bares UserControl
构成DependencyProperty
,INotifyPropertyChanged
消耗Label
,并将绑定与之比较一个ViewModelUserControl
。
文件MainWindow.xaml:
DataContext
代码隐藏的MainWindow.xaml.cs:
UserControl1
MainWindow
的ViewModel,文件ViewModelWindow.cs:
Label
文件UserControl1.xaml:
<Window x:Class="UserControlWithinUserControlDataContext.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Local="clr-namespace:UserControlWithinUserControlDataContext"
Title="MainWindow"
Height="350" Width="525"
>
<StackPanel Orientation="Horizontal"
>
<ListBox SelectedItem="{Binding Text, Mode=TwoWay}"
x:Name="listbox"
Height="150"
>
</ListBox>
<Local:UserControl1 Text="{Binding Text, Mode=OneWay}"
Height="50" Width="150"
/>
<Label Content="{Binding Text, Mode=OneWay}"
/>
</StackPanel>
</Window>
代码隐藏文件UserControl1.xaml.cs:
public partial class MainWindow : Window
{
public ViewModelWindow view_model_window
{
get { return _view_model; }
}
private ViewModelWindow _view_model = new ViewModelWindow();
public MainWindow()
{
InitializeComponent();
DataContext = view_model_window;
IList<String> list = new List<String>();
list.Add("A");
list.Add("B");
list.Add("C");
listbox.ItemsSource = list;
}
}
MainWindow
的ViewModel,文件ViewModelUserControl.cs:
public class ViewModelWindow : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public String Text
{
get { return text; }
set
{
if (text != value)
{
text = value;
NotifyPropertyChanged("Text");
}
}
}
private String text = "Bli";
}
正如您在执行此代码时所看到的那样,<UserControl x:Class="UserControlWithinUserControlDataContext.UserControl1"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Content="{Binding Text}"
Background="Magenta"
HorizontalAlignment="Stretch"
/>
</Grid>
</UserControl>
的{{1}}会更新, public partial class UserControl1 : UserControl
{
public ViewModelUserControl view_model_usercontrol
{
get { return _view_model; }
}
private ViewModelUserControl _view_model = new ViewModelUserControl();
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 FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(TextPropertyChangedCallback)));
private static void TextPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UserControl1 user_control = d as UserControl1;
if(user_control != null)
{
user_control.view_model_usercontrol.Text = user_control.Text;
}
}
public UserControl1()
{
InitializeComponent();
DataContext = view_model_usercontrol;
}
}
的{{1}}则不会。
我做错了什么?有没有办法让它有效?
非常感谢任何线索。
答案 0 :(得分:0)
首先,您不需要在UserControl中仅添加XAML中的任何内容。删除UserControl的所有代码并尝试。
让我们解释一下原因:
Content =“{Binding Text}”你在usercontrol xaml中设置它,它绑定到ViewModelWindow。这很有效。并删除
<Local:UserControl1 => Text="{Binding Text, Mode=OneWay}"
好的,但是在其他情况下在用户控件中定义属性是正确的吗?这是正确的,为了做到这一点:
<UserControl x:Name="UserControlInstance"...>
<Label Content="{Binding Text, ElementName=UserControlInstance}" ...>
在这种情况下,Text是依赖属性,而不是datacontext属性。
尝试第一个选项,然后第二个选项只定义一个依赖项属性,在这种情况下绑定依赖项属性。 还有一个提示,如果依赖属性在可视元素树中,就像你的情况一样,你不需要调用回调。
答案 1 :(得分:0)
感谢Juan的回答,这是在MVVM模式中构思UserControl
的解决方案:
我将名称root
提供给Grid
的{{1}}并设置其UserControl1
:
DataContext
而不是:
root.DataContext = view_model_usercontrol;
一切正常。
快乐结局:)