使用 ItemsControl 中 TextBlock 的值过滤 ListBox 中的集合
Filter Collection in ListBox using value of TextBlock in ItemsControl
我已经创建了自己的日历。我日历中的每一天都是一个 itemsControl,它包含一个文本块和一个列表框,其中应该包含每个日期的项目。
如何使用 ItemsControl 中绑定文本块的字符串值过滤集合?
文本块与日期 属性 绑定 Class。
视图模型
public ObservableCollection<Day> Days { get; set; }
public ObservableCollection<Scene> SceneList;
private ListCollectionView _sceneCollection;
public ListCollectionView SceneCollection
{
get
{
if (_sceneCollection == null) //important for loading the app
{
_sceneCollection = new ListCollectionView(this.SceneList);
_sceneCollection.IsLiveFiltering = true;
_sceneCollection.Filter = o =>
{
var Scene = o as Scene;
return Scene != null && Scene.Date == ////string of binded TextBlock//;
};
}
return _sceneCollection;
}
set
{
_sceneCollection = value; RaisePropertyChanged();
}
}
型号
public class Day : INotifyPropertyChanged
{
private DateTime date;
public DateTime Date
{
get { return date; }
set
{
date = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Date"));
}
}
}
Xaml
<ItemsControl ItemsSource="{Binding Days}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="6" Columns="7">
</UniformGrid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Date , Converter={StaticResource DateConverter}, ConverterParameter=DAY}"/>
<ListBox ItemsSource="{Binding SceneCollection}" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True" Height="100">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock>
<Run Text="{Binding Path=SceneNumber}"/>
<Run Text="{Binding Path=SlugLine}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
首先,您的 ListBox 的 ItemsSource
绑定将不起作用,因为它的 DataContext 是 Day 对象,而 SceneCollection
属性 不存在,但在您的 ViewModel 中。
此外,您不应在 ViewModel 中过滤您的集合,因为所有项目都将绑定到它并且它们需要不同的过滤器。
在你的例子中,如果你想使用过滤器和集合视图,同时保持底层集合不变,我只需添加一个 'ICollectionView' 属性 到你的 'Day' class,并为每一天分配 SceneCollection 的过滤视图。
型号:
public class Day : INotifyPropertyChanged
{
private DateTime date;
public DateTime Date
{
get { return date; }
set
{
date = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Date"));
}
}
private ICollectionView scenes;
public ICollectionView Scenes
{
get { return scenes; }
set
{
scenes = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Scenes"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
ViewModel(示例),在您的 Days 集合中初始化:
private IEnumerable<Day> CreateDaysData()
{
var maxDays = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
for (int d = 1; d <= maxDays; d++)
{
var day = new Day
{
Date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, d)
};
var viewSource = new CollectionViewSource
{
Source = ScenesCollection
};
viewSource.Filter += new FilterEventHandler((o, e) =>
{
e.Accepted = (e.Item as Scene).Date == day.Date;
});
day.Scenes = viewSource.View;
yield return day;
}
}
最后,你的 XAML 会变成这样:
<ItemsControl ItemsSource="{Binding Days}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="6" Columns="7">
</UniformGrid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Date , Converter={StaticResource DateConverter}, ConverterParameter=DAY}"/>
<!-- The ListBox's ItemsSource is bound to the ICollectionView of your Day class -->
<ListBox ItemsSource="{Binding Scenes}" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True" Height="100">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock>
<Run Text="{Binding Path=SceneNumber}"/>
<Run Text="{Binding Path=SlugLine}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我已经创建了自己的日历。我日历中的每一天都是一个 itemsControl,它包含一个文本块和一个列表框,其中应该包含每个日期的项目。
如何使用 ItemsControl 中绑定文本块的字符串值过滤集合? 文本块与日期 属性 绑定 Class。
视图模型
public ObservableCollection<Day> Days { get; set; }
public ObservableCollection<Scene> SceneList;
private ListCollectionView _sceneCollection;
public ListCollectionView SceneCollection
{
get
{
if (_sceneCollection == null) //important for loading the app
{
_sceneCollection = new ListCollectionView(this.SceneList);
_sceneCollection.IsLiveFiltering = true;
_sceneCollection.Filter = o =>
{
var Scene = o as Scene;
return Scene != null && Scene.Date == ////string of binded TextBlock//;
};
}
return _sceneCollection;
}
set
{
_sceneCollection = value; RaisePropertyChanged();
}
}
型号
public class Day : INotifyPropertyChanged
{
private DateTime date;
public DateTime Date
{
get { return date; }
set
{
date = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Date"));
}
}
}
Xaml
<ItemsControl ItemsSource="{Binding Days}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="6" Columns="7">
</UniformGrid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Date , Converter={StaticResource DateConverter}, ConverterParameter=DAY}"/>
<ListBox ItemsSource="{Binding SceneCollection}" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True" Height="100">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock>
<Run Text="{Binding Path=SceneNumber}"/>
<Run Text="{Binding Path=SlugLine}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
首先,您的 ListBox 的 ItemsSource
绑定将不起作用,因为它的 DataContext 是 Day 对象,而 SceneCollection
属性 不存在,但在您的 ViewModel 中。
此外,您不应在 ViewModel 中过滤您的集合,因为所有项目都将绑定到它并且它们需要不同的过滤器。
在你的例子中,如果你想使用过滤器和集合视图,同时保持底层集合不变,我只需添加一个 'ICollectionView' 属性 到你的 'Day' class,并为每一天分配 SceneCollection 的过滤视图。
型号:
public class Day : INotifyPropertyChanged
{
private DateTime date;
public DateTime Date
{
get { return date; }
set
{
date = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Date"));
}
}
private ICollectionView scenes;
public ICollectionView Scenes
{
get { return scenes; }
set
{
scenes = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Scenes"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
ViewModel(示例),在您的 Days 集合中初始化:
private IEnumerable<Day> CreateDaysData()
{
var maxDays = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
for (int d = 1; d <= maxDays; d++)
{
var day = new Day
{
Date = new DateTime(DateTime.Now.Year, DateTime.Now.Month, d)
};
var viewSource = new CollectionViewSource
{
Source = ScenesCollection
};
viewSource.Filter += new FilterEventHandler((o, e) =>
{
e.Accepted = (e.Item as Scene).Date == day.Date;
});
day.Scenes = viewSource.View;
yield return day;
}
}
最后,你的 XAML 会变成这样:
<ItemsControl ItemsSource="{Binding Days}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="6" Columns="7">
</UniformGrid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Date , Converter={StaticResource DateConverter}, ConverterParameter=DAY}"/>
<!-- The ListBox's ItemsSource is bound to the ICollectionView of your Day class -->
<ListBox ItemsSource="{Binding Scenes}" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True" Height="100">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock>
<Run Text="{Binding Path=SceneNumber}"/>
<Run Text="{Binding Path=SlugLine}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>