我正在使用一个ObservableCollection带有两个ICollectionView不同的过滤器.
一种用于按某种类型过滤消息,一种用于计算已检查的消息.正如您所看到的,消息过滤器和消息计数工作正常,但是当我取消检查时,消息将从列表中消失(计数仍然有效).
对于这篇长篇文章,我很抱歉,我想包括所有相关内容.
XAML代码:
<!-- Messages List -->
<DockPanel Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
Height="500">
<ListBox Name="listBoxZone"
ItemsSource="{Binding filteredMessageList}"
Background="Transparent"
BorderThickness="0">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Name="CheckBoxZone"
Content="{Binding text}"
Tag="{Binding id}"
Unchecked="CheckBoxZone_Unchecked"
Foreground="WhiteSmoke"
Margin="0,5,0,0"
IsChecked="{Binding isChecked}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
<Button Content="Test Add New"
Grid.Column="2"
Height="25"
HorizontalAlignment="Left"
Margin="34,2,0,0"
Click="button1_Click" />
<Label Content="{Binding checkedMessageList.Count}"
Grid.Column="2"
Height="25"
Margin="147,2,373,0"
Width="20"
Foreground="white" />
Run Code Online (Sandbox Code Playgroud)
截图:

码:
/* ViewModel Class */
public class MainViewModel : INotifyPropertyChanged
{
// Constructor
public MainViewModel()
{
#region …Run Code Online (Sandbox Code Playgroud) c# wpf observablecollection collectionviewsource icollectionview
ObservableCollection为每个对它们执行的操作发出通知.首先,他们没有批量添加或删除调用,其次他们不是线程安全的.
这不会让他们变慢吗?我们有更快的选择吗?有人说ICollectionView缠得ObservableCollection很快?这种说法有多正确.
我有一个ObservableCollection和一个WPF UserControl是Databound.Control是一个图表,显示ObservableCollection中每个BarData类型项的垂直条.
ObservableCollection<BarData>
class BarData
{
public DateTime StartDate {get; set;}
public double MoneySpent {get; set;}
public double TotalMoneySpentTillThisBar {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
现在我想基于StartDate对ObservableCollection进行排序,以便BarData将在集合中按StartDate的顺序递增.然后我可以像这样计算每个BarData中TotalMoneySpentTillThisBar的值 -
var collection = new ObservableCollection<BarData>();
//add few BarData objects to collection
collection.Sort(bar => bar.StartData); // this is ideally the kind of function I was looking for which does not exist
double total = 0.0;
collection.ToList().ForEach(bar => {
bar.TotalMoneySpentTillThisBar = total + bar.MoneySpent;
total = bar.TotalMoneySpentTillThisBar;
}
);
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用ICollectionView对数据进行排序,过滤数据但不会改变实际的集合.我需要对实际集合进行排序,以便我可以为每个项目计算TotalMoneySpentTillThisBar.它的价值取决于集合中的项目顺序.
谢谢.
是否有任何方法可以自动更新过滤器,ICollectionView而无需Refresh()在进行相关更改时进行调用?
我有以下内容:
[Notify]
public ICollectionView Workers { get; set; }
Run Code Online (Sandbox Code Playgroud)
此属性中的[Notify]属性刚刚实现,INotifyPropertyChanged但在这种情况下它似乎没有做任何事情.
Workers = new CollectionViewSource { Source = DataManager.Data.Workers }.View;
Workers.Filter = w =>
{
Worker worker = w as Worker;
if (w == null)
return false;
return worker.Employer == this;
};
Run Code Online (Sandbox Code Playgroud)
在XAML中:
<TextBlock x:Name="WorkersTextBlock"
DataContext="{Binding PlayerGuild}"
FontFamily="Pericles"
Text="{Binding Workers.Count,
StringFormat=Workers : {0},
FallbackValue=Workers : 99}" />
Run Code Online (Sandbox Code Playgroud)
更新:看起来使用ICollectionView对我来说是必要的,所以我想重新审视这个主题.我正在为这个问题添加一笔赏金,其收件人将是任何能够提供有关如何实现ICollectionView不需要手动刷新的"不干涉"的洞察力的人.在这一点上,我对任何想法持开放态度.
任何人都可以帮我正确实现ICollectionViewLiveShaping过滤目的吗?关于这个问题,我没有在网上找到很多有用的文档.这就是我所拥有的:
public ICollectionView WorkersEmployed { get; set; }
WorkersEmployed = new CollectionViewSource { Source = GameContainer.Game.Workers }.View;
Run Code Online (Sandbox Code Playgroud)
我没有使用,GetDefaultView因为我需要在此集合上有多个过滤器实例.如果重要,那GameContainer.Game.Workers就是ObservableCollection.
ApplyFilter(WorkersEmployed);
private void ApplyFilter(ICollectionView collectionView)
{
collectionView.Filter = IsWorkerEmployed;
}
public bool IsWorkerEmployed(object item)
{
Worker w = item as Worker;
return w.EmployerID == this.ID;
}
Run Code Online (Sandbox Code Playgroud)
这一切都有效,但当然必须手动刷新,这就是我尝试使用的原因ICollectionViewLiveShaping.我能找到的最好的例子就是这个,但不幸的是我仍然无法让它发挥作用.鉴于我在这里有什么,任何人都可以给我一个正确的方向,让实时过滤工作?
任何帮助将不胜感激.
出于好奇,这真的是一项艰巨的任务吗?如果是这样的话,设计人员似乎ICollectionViewLiveShaping做得很糟糕.
更新:看来,只有这样,才能增加一个属性LiveFilteringProperties的ICollectionViewLiveShaping通过字符串收集.鉴于这种限制,是否可以按另一个类中的属性进行过滤(在本例中为Workers'EmployerID)?
任何有经验的人都能GetDefaultView告诉我,在这种情况下我想做什么甚至是一个可行的选择吗?老实说我不知道是不是因为缺乏文档和可用的例子.即使这是不可行的,也至少知道我是否在浪费时间.
我已经绑定了GridView一个ICollectionView在XAML设计器中的属性未知,因为CollectionView已经转换为类型Object的实体并且无法访问实体属性,它运行良好没有错误但设计者将其显示为错误,如果我绑定到我可以访问属性的集合
示例实体是一个Person具有string Name属性的我将它们放在一个ObservableCollection<Person>并从中获取视图并将其绑定到GridView.ItemsSource现在当我尝试设置列标题DataMemberBinding.FirstName属性时,设计器将其显示为错误
无法在类型对象的数据上下文中解析属性'FirstName'
这是一个错误还是Resharper在我身上耍花招
示例代码:
public class Person
{
public string FirstName{
get { return _firstName; }
set { SetPropertyValue("FirstName", ref _firstName, value); }
}
}
public class DataService
{
public IDataSource DataContext { get; set; }
public ICollectionView PersonCollection{ get; set; }
public DataService()
{
DataContext = new DataSource();
//QueryableCollectionView is from Telerik
//but if i use any other CollectionView …Run Code Online (Sandbox Code Playgroud) 我在WPF,.NET 4.0中的DataGrid控件上绑定ICollectionView的属性类型.
我用Filter了ICollectionView.
public ICollectionView CallsView
{
get
{
return _callsView;
}
set
{
_callsView = value;
NotifyOfPropertyChange(() => CallsView);
}
}
private void FilterCalls()
{
if (CallsView != null)
{
CallsView.Filter = new Predicate<object>(FilterOut);
CallsView.Refresh();
}
}
private bool FilterOut(object item)
{
//..
}
Run Code Online (Sandbox Code Playgroud)
Init ICollection视图:
IList<Call> source;
CallsView = CollectionViewSource.GetDefaultView(source);
Run Code Online (Sandbox Code Playgroud)
我试图解决这个问题:
例如,源数据计数为1000个项目.我使用过滤器,在DataGrid控件中我只显示200个项目.
我想将ICollection当前视图转换为IList<Call>
我有一个WPF ListView控件,ItemsSource设置为以这种方式创建的ICollectionView:
var collectionView =
System.Windows.Data.CollectionViewSource.GetDefaultView(observableCollection);
this.listView1.ItemsSource = collectionView;
Run Code Online (Sandbox Code Playgroud)
...其中observableCollection是复杂类型的ObservableCollection.ListView配置为为每个项目显示复杂类型上的一个字符串属性.
用户可以刷新ListView,此时我的逻辑存储当前所选项的"键字符串",重新填充底层的observableCollection.然后将先前的排序和过滤器应用于collectionView.此时我想"重新选择"在刷新请求之前选择的项目.observableCollection中的项是新实例,因此我比较各自的字符串属性,然后选择匹配的字符串属性.像这样:
private void SelectThisItem(string value)
{
foreach (var item in collectionView) // for the ListView in question
{
var thing = item as MyComplexType;
if (thing.StringProperty == value)
{
this.listView1.SelectedItem = thing;
return;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这一切都有效.如果选择了第4项,并且用户按下F5,则重构列表,然后选择具有与前4项相同的字符串属性的项.有时这是新的第4项,有时不是,但它提供了" 最不惊讶的行为 ".
当用户随后使用箭头键在ListView中导航时,问题就出现了.刷新后的第一个向上或向下箭头会导致(新)列表视图中的第一个项目被选中,而不管前一个逻辑选择了哪个项目.任何进一步的箭头键按预期工作.
为什么会这样?
这显然违反了"最不惊讶"的规则.我怎么能避免呢?
编辑
进一步搜索,这似乎与未答复的
WPF ListView箭头导航和击键问题描述的相同异常,除了我提供更多细节.
当您单击a中的列标题时,这是默认的排序方法DataGrid.当基础列表包含100,000个项目时,刷新视图大约需要20秒.SortDescription在a上设置s 时可以观察到相同的延迟CollectionView.
通过使用ListCollectionView.CustomSort或通过排序和重新分配列表进行排序几乎立即起作用.
为什么会这么拖延?这只是对绑定属性的"反思税"吗?
有些情况下,由于大量的INotifyChangedProperties事件,您有许多UI更新.在这种情况下,您可能只想在批量设置所有属性时仅向UI发出一次更改信号.
我发现这篇很棒的文章解释了如何推迟ViewCollection的刷新:
http://marlongrech.wordpress.com/2008/11/22/icollectionview-explained/
但是当View被推迟时我得到一个例外,我尝试在集合中添加一些东西.我不明白为什么不允许这样做.这就是它的第一点.
InvalidoperationException: 在延迟刷新时无法更改或检查CollectionView的内容或当前位置.
有谁知道如何解决这个问题?非常感谢,