【问题标题】:How to avoid creating instance of View with MVVM (WPF)如何避免使用 MVVM (WPF) 创建视图实例
【发布时间】:2015-11-30 16:40:20
【问题描述】:

我刚刚意识到,每次我使用 MVVM 并尝试用它的 View 显示 ViewModel 时,都会创建一个 View 的实例,尽管我只是使用相同的 ViewModel。

在我的视图中是一个 GridView。我在代码隐藏中写了这个来调用 ViewModel 的事件。

private void gridView_SelectionChanged(object sender, SelectionChangeEventArgs e)
{
    DataContext.CallOnClick((DataContext as IHasSelectedItem<IViewModel>)?.SelectedItem);
}

问题在于,如果我在 View 的代码隐藏中定义了一些事件,我将多次获得这些事件,因为 View 的实例总是被创建并且每个实例都向 ViewModel 发送事件。

有没有人也有这个问题。或者有人知道解决方案吗?非常感谢!

------------------------------------------ -----------------

添加: 我已经像这样更改了我的代码隐藏。它有效,我只得到了一次事件。但我不确定其他观点是否已被处理。

public TestView()
{
   InitializeComponent();
   IsVisibleChanged += TestView_IsVisibleChanged;
}

private void TestView_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
   if (e.NewValue.Equals(false))
   {
       MyGridView.SelectionChanged -= gridView_SelectionChanged;                
   }
   else
   {
       MyGridView.SelectionChanged += gridView_SelectionChanged;
   }
}

private void gridView_SelectionChanged(object sender, SelectionChangeEventArgs e)
{
   DataContext.CallOnClick((DataContext as IHasSelectedItem<IViewModel>)?.SelectedItem);
}

【问题讨论】:

  • 你必须取消订阅你的活动然后订阅它会解决你的问题。
  • 为什么创建 ViewModel 会创建新的 View 实例?在 MVVM 模式中,ViewModel 不知道 View。因此,您可以通过 View 的属性创建 View 并传递 ViewModel,这样您就可以为不同的 ViewModel 使用相同的 View
  • 你能edit你的问题包括你用来显示视图的代码吗?
  • 使用 MVVM 模式,您的代码隐藏视图中不应该有任何代码。如果您需要一些东西,您可以编写附加属性或使用 EventToCommand-Binding。请向我们展示您的代码隐藏代码
  • @TomTom - MVVM 模式允许有代码隐藏代码。但是代码必须只包含 View 的逻辑

标签: wpf mvvm view viewmodel


【解决方案1】:

针对您的问题的 MVVM 解决方案是使用IsVisibleChanged 事件。取而代之的是,我们只需在视图模型中创建一个bool 属性:

private bool isVisible = false;

public bool IsVisible
{
    get { return isVisible; }
    set { isVisible = value; NotifyPropertyChanged("IsVisible"); }
}

现在您可以使用BooleanToVisibilityConverter 将此属性数据绑定到相关控件的Visibility 属性:

Visibility="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"

现在,每当Visibility 属性发生变化时,IsVisible 设置器就会被调用,因此您可以在那里处理它:

public bool IsVisible
{
    get { return isVisible; }
    set 
    {
        isVisible = value; 
        NotifyPropertyChanged("IsVisible");
        // Handle the change of visibility here... maybe call a method from here?
    }
}

【讨论】:

  • 我不想使用可见性来控制事件处理程序。我只需要一种方法将我的事件处理程序绑定到仅查看一次,并尽量避免多次获取事件。 Visibility 的方式确实是一个技巧。而且我不知道 View 的实例是否已经被释放。
  • 当不再有任何对它们的实时引用时,WPF 将处理它们,因此删除事件处理程序应该可以解决问题。
  • 这意味着,当我从视图中删除事件处理程序时,其余的将由 GC 完成。好的,这就是重点。我曾担心过,视图不会被真正处理掉。
猜你喜欢
  • 1970-01-01
  • 2018-03-12
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 2018-03-10
  • 2011-06-03
  • 1970-01-01
相关资源
最近更新 更多