2012-07-24 55 views
2

我最近为我的一个域实体添加了一个Disabled属性。我在视图模型中有这些实体的List<T>。我只是改变了吸气剂,以基于UI设置筛选列表以选择性地显示被禁用的项目。如何添加到ObservableCollection <T>项目与LINQ Getter中的哪里()?

public ObservableCollection<CustomVariableGroup> CustomVariableGroups 
{ 
    get 
    { 
     if (this.ShowDisabled) { return this._customVariableGroups; } 

     return new ObservableCollection<CustomVariableGroup>(this._customVariableGroups.Where(x => x.Disabled == false)); 
    } 
} 

的问题是,当我现在尝试这样做(在同一视图模型),该项目不会被添加到集合。

this.CustomVariableGroups.Add(newGroup); 

而且我想我知道为什么:被添加到新ObservableCollection<T>的新闻组,不_customVariableGroups的支持字段。

如果LINQ Where()扩展方法能够返回ObservableCollection<T>(私有支持字段本身的类型)而不是IEnumerable,我不认为我会遇到这个问题。现在,因为Where()返回IEnumerable<T>,我需要将其包装在新的ObservableCollection<T>中。

我在同一个视图模型中添加新项目的权利/最佳方式是什么?我是否需要直接将其添加到私人支持字段?我不想这样做,因为我不想记住不要使用该属性本身。

+0

这就是为什么我寻求帮助,芽。不要只是把它称为不好,你能建议如何做对吗? – 2012-07-24 13:39:22

+0

每次你打电话给你的财产,一个**新的**可观察收藏品被创造.... – 2012-07-24 13:39:33

+0

我意识到这一点。 – 2012-07-24 13:40:14

回答

1

而不是绑定直接添加到您的收藏夹中,您可以绑定到一个ICollectionView并在您的Disabled属性中设置一个Filter。无需更改源集合。

编辑:

视图模型:

//this collection just init once - eg. in ctor, use add, remove, clear to alter 
public ObservableCollection<CustomVariableGroup> CustomVariableGroups {get; private set; } 
//create just once in ctor 
public ICollectionView MyView {get; private set;} 

//ctor 
this.CustomVariableGroups = new ObservableCollection<CustomVariableGroup>(); 
this.MyView = CollectionViewSource.GetDefaultView(this.CustomVariableGroups); 

//in your disabled property set the filter 
    public bool ShowDisabled 
    { 
     get { return _showDisabled; } 
     set { 
      _showDisabled = value; 

      if (_showDisabled) 
       //show just disabled 
       this.MyView.Filter = (item) => 
             { 
              var myitem = (CustomVariableGroup) item; 
              return myitem.Disabled; 
             }; 
      else 
      { 
       //show all 
       this.MyView.Filter = (item) => { return true; }; 
      } 


      this.NotifyPropertyChanged("ShowDisabled"); } 
    } 

XAML

<CheckBox Content="ShowDisabled" IsChecked="{Binding ShowDisabled}"/> 
    <ListBox ItemsSource="{Binding MyView}" Grid.Row="1"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Name}"/> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 

这部作品在我的testproject

+0

你能举个例子吗?这是XAML还是C#? – 2012-07-24 14:22:41

+0

完成后,看我的编辑 – blindmeis 2012-07-25 09:05:56

+0

谢谢!目前我无法尝试此操作。我应该可以在今晚或明天尝试。 – 2012-07-25 12:28:41

0

我会维护你的支持列表,然后提高为你的ObservableCollection更改的属性。

public ObservableCollection<CustomVariableGroup> CustomVariableGroups 
{ 
    get 
    { 
     if (this.ShowDisabled) { return this._customVariableGroups; } 

     return new ObservableCollection<CustomVariableGroup> (this._customVariableGroups.Where(x => x.Disabled == false)); 
    } 
} 

// adds to the backing list but raises on property to rebuild and 
// return the ObservableCollection 
public void AddCustomVariableGroup(CustomVariableGroup newGroup) 
{  
    this._customVariableGroups.Add(newGroup); 
    OnPropertyChanged("CustomVariableGroups"); 
} 

//Example invocation 
AddCustomVariableGroup(newGroup); 
+0

谢谢,但现在开发人员必须记住不要使用该属性。我试图避免这种情况。 – 2012-07-24 14:28:43

0

我在使用WinPhone应用程序显示过滤结果时遇到类似问题。我的解决方案是绑定到“ShowDisabled”属性更改并在此事件上简单地Clear(),并在本例中将内容读入主Observable:CustomVariableGroups。事情是这样的:

public bool ShowDisabled 
{ 
    get 
    { 
     return showDisabled; 
    } 
    set 
    { 
     if (showDisabled!= value) 
     { 
      showDisabled = value; 
      NotifyPropertyChanged("ShowDisabled"); 
     } 
    } 
} 

在构造函数中添加此:this.PropertyChanged += new PropertyChangedEventHandler(MyViewModel_PropertyChanged);

而在事件处理程序:

void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "ShowDisabled") 
    { 
     CustomVariableGroups.Clear(); 
     foreach (var cvg in AllVariableGroups.Where(x => !x.Disabled)) 
     { 
      CustomVariableGroups.Add(cvg); 
     } 
    } 
} 

绑定到CustomVariableGroups组件应相应地更新。

免责声明:当然这会对性能产生影响,您需要确定它是否可以忽略不计。

+0

这不起作用。通过在执行Linq查询之前清除集合,您正在查询一个空集合。 – JKor 2012-07-24 13:52:07

+0

哎呦,对不起,我只是从现有的代码复制粘贴并更改名称。当然,他需要从一个始终包含所有元素的支持属性进行查询,或者在清除集合然后添加之前进行查询。我编辑了答案。 – Tallmaris 2012-07-24 13:58:53

+0

@Tallmaris谢谢,但这看起来更像是一种解决方法,而不是一种正确的方法。我希望更简单/干净/优雅的东西。 – 2012-07-24 14:27:22

0

我会做类似@Tallmaris,但不是这样的MyViewModel_PropertyChanged

 CustomVariableGroups.Clear(); 
    foreach (var cvg in CustomVariableGroups.Where(x => !x.Disabled)) 
    { 
     CustomVariableGroups.Add(cvg); 
    } 

这样做:

 foreach(var cvg in CustomVariableGroups.Where(x => x.Disabled)) 
    { 
     CustomVariableGroups.Remove(cvg); 
    } 

如果不工作(取决于是否Enumerable.Where我认为),你可以这样做:

 foreach(var cvg in Custom VariableGroups.Where(x=> x.Disabled).ToList()) 
    { 
     CustomVariableGroups.Remove(cvg); 
    } 
1

正如在评论中提到的,正确的方式来解决,这是在视图,而不是视图模型。这只是一个观点。我想我会发布我如何处理它,以防万一这有助于别人。

首先,吸气剂(视图模型)应该每次只返回完整列表:

public ObservableCollection<CustomVariableGroup> CustomVariableGroups 
{ get { return this._customVariableGroups; } } 

然后,在视图中,我添加了过滤器事件我CollectionViewSource:

<CollectionViewSource x:Key="SortedGroups" Source="{Binding CustomVariableGroups}" Filter="CollectionViewSource_Filter"> 

每次点击Show Disabled复选框时都会刷新列表:

Command="{Binding RefreshVariableGroupCommand}" 

然后,在第E码后面,我实现了过滤器:

private void CollectionViewSource_Filter(object sender, FilterEventArgs e) 
{ 
    CustomVariableGroup customVariableGroup = e.Item as CustomVariableGroup; 

    if (customVariableGroup == null) { return; } 

    if ((bool)chkShowDisabled.IsChecked) 
    { 
     // Show everything 
     e.Accepted = true; 
     return; 
    } 

    // We are not showing disabled items, so set disabled items e.Accepted to false. 
    if (customVariableGroup.Disabled == true) 
    { 
     e.Accepted = false; 
     return; 
    } 

    e.Accepted = true; 
} 

这个唯一的一部分,我不喜欢,是我使用MVVM并试图避免代码隐藏类。但是,最好是拥有这个视觉模型。

+0

你可以在你的viewmodel中做同样的事情,看我的答案 – blindmeis 2012-07-25 10:34:46

相关问题