Caliburn Micro - 如何公开属性,解决用户控件 WPF 中的绑定问题
我正在使用 Caliburn Micro 学习 MVVM。我有两个视图:ShellView
(主窗口)和PersonView
(UserControl)。 ShellView 正确绑定到 ShellViewModel 没有任何问题,但它似乎没有正确地将用户控件绑定到其关联的 ViewModel。
我有一个在 ShellViewModel
中初始化的属性 MyPerson
,它与 ShellView
中控件的 x:Name
相匹配,通过CM 约定它应该将 DataContext 绑定到 PersonViewModel (我从 this SO发布),但事实并非如此。绑定标签显示 CMTestUserControlMVVM.ViewModels.ShellViewModel
。
我明确地将 DataContext 添加到 UserControl 中的 ViewModel 来解决此问题。
DataContext="CMTestUserControlMVVM.ViewModels.PersonViewModel"
我使用绑定标签验证了它,因为它显示 CMTestUserControlMVVM.ViewModels.PersonViewModel
,但我现在遇到以下问题:
- ViewModel 中的属性和操作未绑定。初始化的 MyPerson 值不会被反映,按钮
SayMyName
不会执行任何操作。 - 这些属性不会暴露在主窗口中。我最终希望将 PersonView 控件的 FirstName 和 LastName 属性绑定到 Shell 视图中的其他控件。
我该如何解决这些问题?以下是相关代码。
ShellView.xaml:
<Window x:Class="CMTestUserControlMVVM.Views.ShellView"
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:CMTestUserControlMVVM.Views"
mc:Ignorable="d"
Title="ShellView" Height="450" Width="800"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Width="100" x:Name="DoSomething" Content="Do Something"/>
<local:PersonView Grid.Row="1" x:Name="MyPerson"
Width="350" Height="100"
/>
<Label Content="{Binding}" Grid.Row="2" />
</Grid>
关联的ViewModel:
namespace CMTestUserControlMVVM.ViewModels
{
public class ShellViewModel : Screen
{
private PersonViewModel model;
public PersonViewModel MyPerson
{
get { return model; }
set
{
model = value;
NotifyOfPropertyChange(() => MyPerson);
}
}
public ShellViewModel()
{
MyPerson = new PersonViewModel()
{
FirstName = "Shameel",
LastName = "Mohammed"
};
}
public void DoSomething()
{
MessageBox.Show("Doing Something");
}
}
}
PersonView.xaml:
<UserControl x:Class="CMTestUserControlMVVM.Views.PersonView"
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:CMTestUserControlMVVM.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
DataContext="CMTestUserControlMVVM.ViewModels.PersonViewModel"
>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="FirstName"/>
<TextBlock x:Name="LastName"/>
</StackPanel>
<Button Grid.Row="1" x:Name="SayMyName" Content="Say My Name!"/>
<Label Grid.Row="2" Content="{Binding}"/>
</Grid>
关联的ViewModel:
namespace CMTestUserControlMVVM.ViewModels
{
public class PersonViewModel : PropertyChangedBase
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
NotifyOfPropertyChange(() => FirstName);
}
}
private string _lastName;
public string LastName
{
get { return _lastName; }
set
{
_lastName = value;
NotifyOfPropertyChange(() => LastName);
}
}
public void SayMyName()
{
MessageBox.Show($"Hi {FirstName} {LastName}!");
}
}
}
I am learning MVVM using Caliburn Micro. I have two views: ShellView
(Main window) and PersonView
(UserControl). The ShellView gets bound properly to the ShellViewModel with no problem, but it doesn't seem to properly bind the usercontrol to its associated ViewModel.
I have a property MyPerson
initialized in ShellViewModel
that matches the x:Name
of the control in the ShellView
, by CM convention it should bind the DataContext to the PersonViewModel (I got this approach from this SO post), but it doesn't. The Binding label shows CMTestUserControlMVVM.ViewModels.ShellViewModel
.
I explicitly added the DataContext to the ViewModel in the UserControl to fix this.
DataContext="CMTestUserControlMVVM.ViewModels.PersonViewModel"
I verified it with the Binding Label as it shows CMTestUserControlMVVM.ViewModels.PersonViewModel
, but I have the following issues now:
- The properties and Actions in the ViewModel are not bound. The initialized MyPerson's values are not reflected and the button
SayMyName
doesnt do anything. - The properties are not exposed to the main window. I ultimately want to bind the FirstName and LastName props of PersonView control to other controls in the Shell View.
How do I fix these? Following are the code associated.
ShellView.xaml:
<Window x:Class="CMTestUserControlMVVM.Views.ShellView"
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:CMTestUserControlMVVM.Views"
mc:Ignorable="d"
Title="ShellView" Height="450" Width="800"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Width="100" x:Name="DoSomething" Content="Do Something"/>
<local:PersonView Grid.Row="1" x:Name="MyPerson"
Width="350" Height="100"
/>
<Label Content="{Binding}" Grid.Row="2" />
</Grid>
Associated ViewModel:
namespace CMTestUserControlMVVM.ViewModels
{
public class ShellViewModel : Screen
{
private PersonViewModel model;
public PersonViewModel MyPerson
{
get { return model; }
set
{
model = value;
NotifyOfPropertyChange(() => MyPerson);
}
}
public ShellViewModel()
{
MyPerson = new PersonViewModel()
{
FirstName = "Shameel",
LastName = "Mohammed"
};
}
public void DoSomething()
{
MessageBox.Show("Doing Something");
}
}
}
PersonView.xaml:
<UserControl x:Class="CMTestUserControlMVVM.Views.PersonView"
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:CMTestUserControlMVVM.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
DataContext="CMTestUserControlMVVM.ViewModels.PersonViewModel"
>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="FirstName"/>
<TextBlock x:Name="LastName"/>
</StackPanel>
<Button Grid.Row="1" x:Name="SayMyName" Content="Say My Name!"/>
<Label Grid.Row="2" Content="{Binding}"/>
</Grid>
Associated ViewModel:
namespace CMTestUserControlMVVM.ViewModels
{
public class PersonViewModel : PropertyChangedBase
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
NotifyOfPropertyChange(() => FirstName);
}
}
private string _lastName;
public string LastName
{
get { return _lastName; }
set
{
_lastName = value;
NotifyOfPropertyChange(() => LastName);
}
}
public void SayMyName()
{
MessageBox.Show(quot;Hi {FirstName} {LastName}!");
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
删除
dataContext =“ cmtestusercontrolmvvv.m.viewmodels.personviewmodel”
,因为这将dataContext
设置为string> string> string
字符串毫无意义。 P>usercontrol
用contentControl
在shellview.xaml中:Remove
DataContext="CMTestUserControlMVVM.ViewModels.PersonViewModel"
as this sets theDataContext
to astring
literal which makes no sense.Replace the
UserControl
with aContentControl
in ShellView.xaml: