从 ViewModel WPF 更新 XAML 中的 ComboBox ObservableCollection 绑定
Updating ComboBox ObservableCollection Binding in XAML from ViewModel WPF
我在 WPF 中工作,并且有一个视图模型 ModifiedReasonViewModel
,这是我的 DataContext
的 XAML 视图。 ComboBox
不显示我在调试时可以在数据上下文中看到的 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));
}
}
}
非常感谢您的帮助!
如果您在运行时重新分配 ReasonLabels
集合,则必须实现 INotifyPropertyChanged
and raise the PropertyChanged
事件,否则绑定将不会注意到更改。
同样,如果您修改集合本身,例如添加或删除项目,集合需要实现 INotifyCollectionChanged
, which provides events to trigger an update in the user interface. The List<T>
type does not implement this interface, use ObservableCollection<T>
instead. It automatically raises the 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
,否则 属性 setter 会触发 PropertyChanged
事件不会被执行。
private void GetReasonLabelsCallback(Func<IEnumerable<LabelFileModel>> getResult)
{
try
{
ReasonLabels = (List<LabelFileModel>) getResult();
}
catch (Exception ex)
{
Messenger.Default.Send(new UnhandledExceptionMessage(this, ex));
}
}
在回调中设置 属性 并从它的 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。
我在 WPF 中工作,并且有一个视图模型 ModifiedReasonViewModel
,这是我的 DataContext
的 XAML 视图。 ComboBox
不显示我在调试时可以在数据上下文中看到的 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));
}
}
}
非常感谢您的帮助!
如果您在运行时重新分配 ReasonLabels
集合,则必须实现 INotifyPropertyChanged
and raise the PropertyChanged
事件,否则绑定将不会注意到更改。
同样,如果您修改集合本身,例如添加或删除项目,集合需要实现 INotifyCollectionChanged
, which provides events to trigger an update in the user interface. The List<T>
type does not implement this interface, use ObservableCollection<T>
instead. It automatically raises the 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
,否则 属性 setter 会触发 PropertyChanged
事件不会被执行。
private void GetReasonLabelsCallback(Func<IEnumerable<LabelFileModel>> getResult)
{
try
{
ReasonLabels = (List<LabelFileModel>) getResult();
}
catch (Exception ex)
{
Messenger.Default.Send(new UnhandledExceptionMessage(this, ex));
}
}
在回调中设置 属性 并从它的 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。