WPF,在 DataContext 更改时更新 ComboBox ItemsSource
WPF, Update ComboBox ItemsSource when it's DataContext changes
我有两个 classes A 和 B,它们都实现了 IThingWithList 接口。
public interface IThingWithList
{
ObservableCollection<int> TheList;
}
A中的列表包含1、2、3
B中的List包含4,5,6
我有一个控制器class,它有一个包含 A 和 B 的 IThingWithList 列表
public class MyControllerClass
{
public ObservableCollection<IThingWithList> Things { get; } = new ObservableCollection<IThingWithList>() { A, B };
public IThingWithList SelectedThing { get; set; }
}
现在,在xaml中我有两个组合框如下
<ComboBox
ItemsSource="{Binding MyController.Things}"
SelectedValue="{Binding MyController.SelectedThing, Mode=TwoWay}" />
<ComboBox
DataContext="{Binding MyController.SelectedThing}"
ItemsSource="{Binding TheList}" />
第一个 ComboBox 控制哪个(A 或 B)是第二个组合框的数据上下文。
问题:
当我select第一个ComboBox的A或B第二个ComboBox的列表项没有更新。
我试过的:
制作 A 和 B ObservableObjects
使 IThingWithList 实现 INotifyPropertyChanged
将 UpdateSourceTrigger 添加到 ItemsSource 绑定
淘Google.
这是我通常如何执行 ViewModel(在您的情况下为“Controller”)Base Class 以获得您正在寻找的功能:
这是所有 VM 派生的基础 class。
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected void SetAndNotify<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(property, value))return;
property = value;
this.OnPropertyChanged(propertyName);
}
}
这是我将如何调整你的控制器Class:
public class MyControllerClass : ViewModelBase
{
private ObservableCollection<IThingWithList> _things;
public ObservableCollection<IThingWithList> Things
{
get => _things;
set { SetAndNotify(ref _things, value); }
}
private IThingWithList _selectedthing;
public IThingWithList SelectedThing
{
get => _selectedThing;
set{SetAndNotify(ref _selectedThing, value);}
}
}
现在调整您的 XAML 以设置容器的 DataContext 而不是每个控件(让生活更轻松)
<UserControl xmlns:local="clr-namespace:YourMainNamespace">
<UserControl.DataContext>
<local:MyControllerClass/>
</UserControl.DataContext>
<StackPanel>
<ComboBox
ItemsSource="{Binding Things}"
SelectedValue="{Binding SelectedThing, Mode=TwoWay}" />
<!-- ComboBox ItemsSource="See next lines" /-->
</StackPanel>
</Window>
您可以将 SelectedThing
更改为 ObservableCollection,或者您可以拥有第二个对象,即列表并进行相应更新:
//Add into MyControllerClass
public MyInnerThingList => SelectedThing.TheList;
//Edit the SelectedThing to look like:
private IThingWithList _selectedthing;
public IThingWithList SelectedThing
{
get => _selectedThing;
set
{
SetAndNotify(ref _selectedThing, value);
RaisePropertyChanged(nameof(MyInnerThingList));
}
}
然后将绑定更改为:
<ComboBox ItemsSource="{Binding MyInnerThingList, Mode=OneWay}" />
您可能还想添加 SelectedMyInnerThing 属性,但不确定是否需要。
我有两个 classes A 和 B,它们都实现了 IThingWithList 接口。
public interface IThingWithList
{
ObservableCollection<int> TheList;
}
A中的列表包含1、2、3 B中的List包含4,5,6
我有一个控制器class,它有一个包含 A 和 B 的 IThingWithList 列表
public class MyControllerClass
{
public ObservableCollection<IThingWithList> Things { get; } = new ObservableCollection<IThingWithList>() { A, B };
public IThingWithList SelectedThing { get; set; }
}
现在,在xaml中我有两个组合框如下
<ComboBox
ItemsSource="{Binding MyController.Things}"
SelectedValue="{Binding MyController.SelectedThing, Mode=TwoWay}" />
<ComboBox
DataContext="{Binding MyController.SelectedThing}"
ItemsSource="{Binding TheList}" />
第一个 ComboBox 控制哪个(A 或 B)是第二个组合框的数据上下文。
问题:
当我select第一个ComboBox的A或B第二个ComboBox的列表项没有更新。
我试过的:
制作 A 和 B ObservableObjects
使 IThingWithList 实现 INotifyPropertyChanged
将 UpdateSourceTrigger 添加到 ItemsSource 绑定
淘Google.
这是我通常如何执行 ViewModel(在您的情况下为“Controller”)Base Class 以获得您正在寻找的功能:
这是所有 VM 派生的基础 class。
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected void SetAndNotify<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(property, value))return;
property = value;
this.OnPropertyChanged(propertyName);
}
}
这是我将如何调整你的控制器Class:
public class MyControllerClass : ViewModelBase
{
private ObservableCollection<IThingWithList> _things;
public ObservableCollection<IThingWithList> Things
{
get => _things;
set { SetAndNotify(ref _things, value); }
}
private IThingWithList _selectedthing;
public IThingWithList SelectedThing
{
get => _selectedThing;
set{SetAndNotify(ref _selectedThing, value);}
}
}
现在调整您的 XAML 以设置容器的 DataContext 而不是每个控件(让生活更轻松)
<UserControl xmlns:local="clr-namespace:YourMainNamespace">
<UserControl.DataContext>
<local:MyControllerClass/>
</UserControl.DataContext>
<StackPanel>
<ComboBox
ItemsSource="{Binding Things}"
SelectedValue="{Binding SelectedThing, Mode=TwoWay}" />
<!-- ComboBox ItemsSource="See next lines" /-->
</StackPanel>
</Window>
您可以将 SelectedThing
更改为 ObservableCollection,或者您可以拥有第二个对象,即列表并进行相应更新:
//Add into MyControllerClass
public MyInnerThingList => SelectedThing.TheList;
//Edit the SelectedThing to look like:
private IThingWithList _selectedthing;
public IThingWithList SelectedThing
{
get => _selectedThing;
set
{
SetAndNotify(ref _selectedThing, value);
RaisePropertyChanged(nameof(MyInnerThingList));
}
}
然后将绑定更改为:
<ComboBox ItemsSource="{Binding MyInnerThingList, Mode=OneWay}" />
您可能还想添加 SelectedMyInnerThing 属性,但不确定是否需要。