【问题标题】:ListView SelectedItem not updating from View Model using MVVM LightListView SelectedItem 未使用 MVVM Light 从视图模型更新
【发布时间】:2017-05-15 09:32:10
【问题描述】:

我正在使用 MVVM 灯将 ListView 绑定到我的 ViewModel 上的 ItemSource。当 ViewModel 上的属性发生更改时,SelectedItem 不会在 View 中更新。

XAML:

<ListView Grid.Row="1" SelectionMode="Single" ItemsSource="{Binding filteredAppListItemSource}" SelectedItem="{Binding selectedApp, Mode=TwoWay}">

视图模型:

public Model.V_PWT_APP_ALL selectedApp { get { return this._selectedApp; } set { this._selectedApp = value; RaisePropertyChanged(() => selectedApp); } }

从视图中选择一个项目会更新 ViewModel,并且所有从 SelectedItem 派生数据的控件都会更新。 TwoWay 绑定似乎不起作用。

【问题讨论】:

    标签: c# wpf listview mvvm-light selecteditem


    【解决方案1】:

    我发现问题出在 SelectedItem 绑定上。我发现我没有正确选择一个项目。我切换到使用 SelectedIndex 并找到正确的索引,并且绑定按预期工作。

    【讨论】:

      【解决方案2】:

      如果您想继续使用 INotified 属性更改界面,您应该按照以下文档设置代码:https://msdn.microsoft.com/en-us/library/ms184414(v=vs.110).aspx

      由于您似乎不是在更改属性,而是更改项目并通知 ItemsSource,因此更好的方法是实现 IObserver/IObservable 接口。这更简单一点,它在模型自己的类中不断更新,整洁且易于管理。这是一个可能的代码示例:

      public class App: IObservable<App>     //where the model class is the IObserver.
      
      {
      
      private App app;
      internal App
      List<IObserver<App>> Observers = new List<IObserver<App>>();
      
      {
      
           get:
                  {
      
                       return app;
                  }
      
           set:
      
                  {
                       app = value;
                       try
                       {
                            foreach (var observer in Observers) observer.OnNext(value);
                            foreach (var observer in Observers) observer.OnCompleted();
                       }
                       catch(Exception ex)
                       {
                            foreach (var observer in Observers) observer.OnError(ex);
                            throw;
                       }
                  }
      }
      

      对于视图模型:

      public Model.V_PWT_APP_ALL selectedApp: IOberver<App>
      {
           List<Control> ControlsToBeUpdated = new List<Control>() //Each control that needs updated should implement and interface that has an .Update(type T) method where T is whatever value needs updated.
           public void OnCompleted()
           {
                //...notify taskBar, etc. 
           }
      
           public void OnError(Exception error)
           {
               //handle exception, update log, etc.
           }
      
           public void OnNext(object value)
           {
               foreach (var control in ControlsToBeUpdated) control.Update(value);
           }
      }
      

      起初这可能看起来很乏味,但它帮助我很好地最小化和管理 ItemsSource 中的更新和错误。最后,我发现在使用 ListView ItemsSource 时控制滚动视图相当繁琐,并且在更新 ItemsSource 并选择滚动视图时,只需使用 ListView.Items.Insert(...) 方法就更好了经常抛出 OutOfRange 异常。这在 MVVM 中可能很难调试。然而,这是另一个话题。我希望这会有所帮助。

      【讨论】:

      • 有趣的方法。但是,这里的 ItemsSource 似乎不是问题。问题是 SelectedItem:SelectedItem="{Binding selectedApp, Mode=TwoWay}" 我正在更新 selectedApp,并执行 RaisePropertyChanged,但所选项目没有改变。
      • 我相信您需要添加一个偶数来处理更改为您的代码的选择。您似乎绑定到加载时选择的应用程序,而不是绑定到在 ListView 中单击的应用程序。不要使用 Model.V_PWT_APP_ALL selectedApp 的设置器,而是创建一个方法来处理 C# 代码中更改的选择,并使用 (sender as ListView).SelectedItem 将 RaisePropertyChanged(() => selectedApp) 放置在该方法中。将事件添加到 SelectionChanged="ListView_SelectionChanged"/>
      • XAML 应该是
      • 我已经有一个 SelectionChanged 事件的处理程序` ` 这在您使用 UI 并单击(选择)项目时有效。从我的视图到视图模型的绑定有效。问题是让 View 根据 ViewModel 中的更改来选择项目。
      • IObserver/IObservable 模式是为基于推送的命令创建的。您的 ViewModel 需要包含 ModelView 的列表以推送更改更新。标准格式已经并入这些 Microsoft 提供的接口中。在 setter 上,您可以简单地调用 ViewModels .OnNext(object o) 方法来更新 ModelView。 NotifyPropertyChanged 不适合从 ViewModel 转到 ModelView,但可以使其工作。 IObserver/IObservable 更好。见msdn.microsoft.com/en-us/library/dd783449(v=vs.110).aspx
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-30
      • 2018-09-03
      • 1970-01-01
      • 2014-08-04
      • 2018-06-30
      • 1970-01-01
      • 2014-01-18
      相关资源
      最近更新 更多