实现与ObservableCollection(C#,WPF)一起更改的属性

时间:2018-08-24 07:41:46

标签: c# wpf xaml observablecollection propertychanged

我有带有“ ProjectList”的组合框:

MainWindow.xaml

<ComboBox ItemsSource="{Binding Path=ProjectList}" IsSynchronizedWithCurrentItem="True" />

元素正在下面的方法中添加并且可以正常工作:

MainViewModel.cs

[AddINotifyPropertyChangedInterface]
public class MainViewModel{

 public ObservableCollection<string> ProjectList { get; internal set; } 
  = new ObservableCollection<string>(); 

  public async Task GetProjects(){
  ...
   foreach (AItem item in....)
   {
     ProjectList.Add(item.name)
   }
 }    
}

注意-我已经安装了“ PropertyChanged.Fody”。

现在,我向xaml添加了第二个ComboBox“ TaskList”:

<ComboBox ItemsSource="{Binding Path=TaskList}" IsSynchronizedWithCurrentItem="True" />

应基于在“ ProjectList”中选择的项目创建此处的列表。方法大致相同,只有一个参数:

public ObservableCollection<string> TaskList { get; internal set; } 
 = new ObservableCollection<string>();

public async Task GetTask(string projectId = ""){
      ...
       foreach (AItem item in....)
       {
         TaskList.Add(item.name2)
       }
 }   

现在,我要将它添加到我的MVVM中。

问题:何时以及如何运行GetTask()?

应该为“ <属性>已更改”而不是为 ObservableCollection TaskList 设置“内部集”?

3 个答案:

答案 0 :(得分:1)

  

当您选择“项目”时,下一个cb应该加载(运行)taskList

然后,您应该将SelectedItem的{​​{1}}属性绑定到字符串源属性,并在此设置方法中调用ComboBox方法,例如:

GetTask

...或在选择更改时调用命令:来自设置器:

    private string _selectedProject;
    public string SelectedProject
    {
        get { return _selectedProject; }
        set
        {
            _selectedProject = value;
            GetTask(_selectedProject);
        }
    }

...或使用interaction trigger通过XAML标记。

属性不应真正在其设置程序中启动异步后台操作。有关此的更多信息,请参考我的答案:

Is wrong to invoke an async method from property setter in WPF view model?

答案 1 :(得分:0)

您需要一个事件,该事件在ProjectList组合框的选定项更改时触发。

如果使用的是后面的代码,则只需将SelectionChanged属性设置为指向函数即可。但是,似乎您正在使用MVVM,因此您需要向组合框添加一个交互触发器,一个用于调用该触发器的命令以及一个用于调用该命令的方法。

将此名称空间添加到窗口:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

更改组合框以包括触发器并公开SelectedItem

           <ComboBox ItemsSource="{Binding Path=ProjectList}" 
                     IsSynchronizedWithCurrentItem="True"
                     SelectedItem="{Binding SelectedProject}" >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <i:InvokeCommandAction Command="{Binding ReloadTasksCommand}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </ComboBox>

然后,在您的ViewModel中,添加ReloadTasksCommand命令。您需要定义命令及其调用的方法。

private ICommand reloadTasks;
public ICommand ReloadTasksCommand => this.reloadTasks?? (this.reloadTasks= new RelayCommand(this.ReloadTasks));

public string SelectedProject{ get; set; }

private void ReloadTasks()
{
    GetTasks(this.SelectedProject);
}

我还为SelectedProject添加了一个属性,该属性绑定到Project组合框的SelectedItem。

RelayCommand在GalaSoft.MvvmLight.CommandWpf库中。还有其他的,这就是我使用的。

答案 2 :(得分:0)

像这样更改组合框:

       <ComboBox ItemsSource="{Binding Path=ProjectList}" 
                 IsSynchronizedWithCurrentItem="True"
                 SelectedItem="{Binding SelectedProject}" >                
       </ComboBox>

ViewModel:

private string _selectedObject;
public string SelectedObject
{
    get { return _selectedObject; }
    set
    {
        _selectedObject = value;
        //OnPropertyChanged(); -- INotifyPropertyChanged no need if Fody
        ReloadTasks();
    }
}

private void ReloadTasks()
{
    GetTasks(SelectedProject);
}