我对MVVM有一点问题。让我先描述一下我的问题。
我有一个父视图(DashboardConsultants),它有一个数据网格。 DataGrid中的每个单元格都有一个工具提示,实现如下:
<UserControl.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type vm:UC1001_AgreementDetailsViewModel}">
<v:UC1001_AgreementDetails_View />
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="DataGridCell.ToolTip">
<Setter.Value>
<vm:UC1001_AgreementDetailsViewModel />
</Setter.Value>
</Setter>
工具提示调用我的ViewModel(AgreementDetailsViewModel),它具有以下代码:
public UC1001_ActiveAgreementContract AgreementDetailsContract { get; set; }
public int AgreementID { get; set; }
public UC1001_AgreementDetailsViewModel()
{
AgreementDetailsContract = new UC1001_ActiveAgreementContract();
this.Initialize();
}
private void Initialize()
{
GetRefData();
ShowAgreementDetailsView();
}
private void GetRefData()
{
UC1001_ActiveAgreementArguments args = new UC1001_ActiveAgreementArguments();
args.AgreementID = 3;
DefaultCacheProvider defaultCacheProvider = new DefaultCacheProvider();
if (!defaultCacheProvider.IsSet("AgrDet:" + args.AgreementID))
{
ConsultantServiceClient client = new ConsultantServiceClient();
AgreementDetailsContract = client.GetAgreementDetailsByAgreementID(args);
defaultCacheProvider.Set("AgrDet:" + args.AgreementID, AgreementDetailsContract, 5);
}
else
{
AgreementDetailsContract = (UC1001_ActiveAgreementContract)defaultCacheProvider.Get("AgrDet:" + args.AgreementID);
}
}
private void ShowAgreementDetailsView()
{
// Initialize
var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
// Show content
var agreementDetailsWorkspace = new Uri("UC1001_AgreementDetails_View", UriKind.Relative);
regionManager.RequestNavigate("ContentRegion", agreementDetailsWorkspace);
}
ViewModel的目标是从数据库获取协议(当前是静态的...),然后将其传递给子视图(UC1001_AgreementDetails_View)以显示为工具提示。子视图具有以下构造函数,因此控件可以绑定到合同:
public UC1001_AgreementDetails_View(ViewModels.UC1001_AgreementDetailsViewModel UC1001_AgreementDetailsViewModel)
{
InitializeComponent();
this.DataContext = UC1001_AgreementDetailsViewModel.AgreementDetailsContract;
}
我在ViewModel Initialize上设置了一个断点,当我进入父View时它会触发,但是当我进入子View时它会触发(因此当打开datagrid中的工具提示时)。有谁知道我怎么解决这个问题?
如果需要,可以提供更多信息/代码。
修改
我尝试了一些东西,现在我得到了类似的东西(我觉得它更接近解决方案)。
我将工具提示更改为以下内容(根据Rachels的帮助):
<Setter Property="DataGridCell.ToolTip">
<Setter.Value>
<v:UC1001_AgreementDetails_View DataContext="{Binding AgreementDetailsViewModel}" />
</Setter.Value>
</Setter>
在我的孩子视图中,我提出了以下绑定
<Label Content="{Binding AgreementDetailsContract.Header}" Height="50" HorizontalAlignment="Left" Margin="8,6,0,0" Name="_labelHoofding" VerticalAlignment="Top" FontSize="22" />
现在我的AgreementDetailsViewModel是一个名为AgreementDetailsContract的属性,包含我想要显示的所有信息,是我子视图的DataContext。但我的问题仍然存在。当打开ConsultantDashboard时,它会在显示工具提示时打开时触发。是否有某种事件/命令可以放在工具提示中以激活ViewModel?此外,我认为标签的绑定有问题,因为它没有显示信息(尽管它可能与ViewModel没有传递正确信息的问题相同)。
同样,如果它看起来有点复杂,我会很乐意进一步解释,或者如果被问到还会提供更多代码。
解决:
我得到了解决方案。我在ChildView的构造函数中指定绑定而不是其XAML或在View Tooltip中指定。
public UC1001_AgreementDetails_View()
{
InitializeComponent();
this.DataContext = new UC1001_AgreementDetailsViewModel();
}
答案 0 :(得分:3)
看起来您的View直接引用了ViewModel,这意味着它会在启动时创建ViewModel的副本
此代码
<Setter Property="DataGridCell.ToolTip">
<Setter.Value>
<vm:UC1001_AgreementDetailsViewModel />
</Setter.Value>
</Setter>
应该是
<Setter Property="DataGridCell.ToolTip">
<Setter.Value>
<!-- If you want to keep the DataTemplate, use a ContentControl -->
<v:UC1001_AgreementDetails_View DataContext="{Binding AgreementDetails}" />
</Setter.Value>
</Setter>
您的数据结构应如下所示:
class MainViewModel
{
ObservableCollection<AgreementViewModel> Agreements;
}
class AgreementViewModel
{
// Loaded only when getter is called
AgreementDetailViewModel AgreementDetails;
}