【问题标题】:Updating ComboBox ObservableCollection Binding in XAML from ViewModel WPF从 ViewModel WPF 更新 XAML 中的 ComboBox ObservableCollection 绑定
【发布时间】:2021-01-24 01:51:17
【问题描述】:

我在 WPF 中工作,并且有一个视图模型 ModifiedReasonViewModel,它是我用于 XAML 视图的 DataContextComboBox 不显示我在调试时可以在数据上下文中看到的 4 项中的任何一项。我认为这肯定与我异步提取原因标签的事实有关。有关如何解决此问题的任何想法?

当我仅使用在构造函数中初始化的测试字符串列表测试此代码时,它按预期工作。

这是我目前在 XAML 中使用的 RadComboBox

d:DataContext="{d:DesignInstance Type=vm:ATMModifiedReasonViewModel, IsDesignTimeCreatable=True}">
<telerik:RadComboBox Name="ReasonCmbo"
                     ItemsSource="{Binding ReasonLabels}" 
                     DisplayMemberPath="Name"
                     IsEditable="False"
                     Margin="2" 
                     Grid.Column="1"
                     Grid.Row="1"
                     Grid.ColumnSpan="2">            
</telerik:RadComboBox>

这是我正在使用的 ViewModel 代码:

public class ATMModifiedReasonViewModel : INotifyPropertyChanged
{
   private List<LabelFileModel> _reasonLabels;

   public List<LabelFileModel> ReasonLabels { get { return _reasonLabels; } set { _reasonLabels = value; } }

   public ATMModifiedReasonViewModel(){
      GetReasonLabels();
   }

   public void GetReasonLabels()
   {
      LabelFileProvider lfProvider = new LabelFileProvider();
      LabelFileModelFilter filter = new LabelFileModelFilter() {LabelDefinition = "ModifiedReason"};
      lfProvider.GetFiltered(filter,10, getResult => GetReasonLabelsCallback(getResult));
   }

   private void GetReasonLabelsCallback(Func<IEnumerable<LabelFileModel>> getResult)
   {
       try
       {
            _reasonLabels = (List<LabelFileModel>) getResult();                
       }   
       catch (Exception ex)
       {
            Messenger.Default.Send(new UnhandledExceptionMessage(this, ex));
       }
   }
}

非常感谢您的帮助!

【问题讨论】:

  • 将属性绑定到View的控件时,ViewModel需要实现INotifyPropertyChanged,以便通知View任何属性值的变化
  • 我之前实现过。我已将其重新添加,但运气不佳。
  • 经过一些测试,似乎实例化列表然后向其中添加项目允许视图解释更改并显示新项目?这看起来有可能吗?

标签: c# wpf xaml silverlight telerik


【解决方案1】:

如果在运行时重新分配ReasonLabels 集合,则必须实现INotifyPropertyChanged 并引发PropertyChanged 事件,否则绑定不会注意到更改。

同样,如果您修改集合本身,例如添加或删除项目,集合需要实现INotifyCollectionChanged,它提供事件来触发用户界面中的更新。 List&lt;T&gt; 类型确实实现此接口,请改用 ObservableCollection&lt;T&gt;。如果集合被修改并因此触发绑定更新,它会自动引发 CollectionChanged 事件。

public class ATMModifiedReasonViewModel : INotifyPropertyChanged
{
   private ObservableCollection<LabelFileModel> _reasonLabels;

   public ObservableCollection<LabelFileModel> ReasonLabels
   {
      get => _reasonLabels;
      set
      {
         if (_reasonLabels = value)
            return;

         _reasonLabels = value;
         OnPropertyChanged();
      } 
   }

   // ...your code here.

   public event PropertyChangedEventHandler PropertyChanged;

   protected virtual void OnPropertyChanged(string propertyName = null)
   {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   }
}

您还必须分配ReasonLabels 属性而不是支持字段_reasonLabels,否则触发PropertyChanged 事件的属性设置器将不会被执行。

private void GetReasonLabelsCallback(Func<IEnumerable<LabelFileModel>> getResult)
{
   try
   {
      ReasonLabels = (List<LabelFileModel>) getResult();                
   }   
   catch (Exception ex)
   {
      Messenger.Default.Send(new UnhandledExceptionMessage(this, ex));
   }
}

【讨论】:

    【解决方案2】:

    在您的回调中设置 属性 并从它的 setter 中引发 PropertyChanged 事件,或者在设置支持字段后在回调中引发 PropertyChanged 事件:

    private void GetReasonLabelsCallback(Func<IEnumerable<LabelFileModel>> getResult)
    {
        try
        {
            _reasonLabels = (List<LabelFileModel>)getResult();
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ReasonLabels )));
        }
        catch (Exception ex)
        {
            Messenger.Default.Send(new UnhandledExceptionMessage(this, ex));
        }
    }
    

    框架需要引发事件才能知道何时刷新 UI。

    【讨论】:

      猜你喜欢
      • 2013-08-07
      • 2013-04-18
      • 2014-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 2011-10-25
      • 1970-01-01
      相关资源
      最近更新 更多