【问题标题】:Viewmodel instantiates before it is neededViewmodel 在需要之前实例化
【发布时间】:2011-12-14 23:33:41
【问题描述】:

我对 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>

tooltip调出我的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) 以显示为工具提示。子 View 具有以下构造函数,因此控件可以绑定到合同:

public UC1001_AgreementDetails_View(ViewModels.UC1001_AgreementDetailsViewModel UC1001_AgreementDetailsViewModel)
    {            
        InitializeComponent();
        this.DataContext = UC1001_AgreementDetailsViewModel.AgreementDetailsContract;
    }

我在 ViewModel Initialize 上放置了一个断点,当我进入父视图时它会触发,但当我进入子视图时它应该会触发(因此在数据网格中打开工具提示时)。有谁知道我该如何解决这个问题?

如果需要,可以提供更多信息/代码。

编辑:

我尝试了一些东西,现在我得到了类似的东西(我觉得更接近解决方案)。

我将工具提示更改为以下内容(根据 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 是我的子视图的 DataContext,它有一个名为 AgreementDetailsContract 的属性,其中包含我想要显示的所有信息。但我的问题仍然存在。 AgreementDetailsViewModels 在打开 ConsultantDashboard 时触发,它应该在显示工具提示时打开。我可以在工具提示上放置某种事件/命令来触发 ViewModel 吗?另外,我认为我的标签的绑定有问题,因为它没有显示信息(尽管 ViewModel 没有传递正确的信息可能是同样的问题)。

同样,如果您觉得它有点复杂,我很乐意进一步解释,或者如果需要,可以提供更多代码。

已解决:

我得到了解决方案。我在 ChildView 的构造函数而不是它的 XAML 或 View Tooltip 中指定绑定。

public UC1001_AgreementDetails_View()
   {
      InitializeComponent();
      this.DataContext = new UC1001_AgreementDetailsViewModel();
   } 

【问题讨论】:

  • 请购买一份框架设计指南。要么阅读自己,要么击败决定你类型名称形式的人。另外,更严肃地说,您是否尝试过制作一个非常简单的原型来重现您的问题?您似乎正在做很多复杂的事情,这些事情可能会以几种不同的方式破坏......
  • 功能的一般概念并不难。我只想将视图显示为工具提示,其中包含来自 ViewModel 的数据。这是我第一次使用 WPF 和 MVVM,所以我真的不知道如何自己解决这个问题 :)
  • 工具提示存在于逻辑树之外,因此它们不会按预期继承 DataContext。我无法花足够的时间查看您的问题,以确定这是否是您问题的根源。您可以在此处搜索数据绑定工具提示,并找到许多有关此问题的问题。我想我也发布了一些关于这个主题的答案......
  • @Will 我不认为这是正确的...菜单在逻辑树之外,但工具提示应该在同一棵树中。我最近更新了一个项目,将一些细节移到 ToolTip 中,而绑定根本没有改变。
  • 尝试在 UserControl 中绑定DataContext={Binding AgreementDetailsViewModel},而不是在 ToolTip 上绑定

标签: c# wpf xaml mvvm viewmodel


【解决方案1】:

看起来您的 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;
}

【讨论】:

  • 我得到了解决方案,请检查我的问题。我将您的答案视为已接受,因为答案对我有帮助。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 2017-08-31
  • 2013-03-11
  • 1970-01-01
  • 2020-04-10
相关资源
最近更新 更多