[英]Filtering DataGrid bound to ViewSource from Entity Framework
我似乎在使用WPF和Entity Framework绑定到数据网格时遇到问题。
为简单起见,我有一个数据库优先应用程序。 我想显示怪物表中的怪物列表,然后根据名称进行过滤。 在winforms中,我可以执行此操作,但是WPF中的Datagrids似乎使我陷入循环
XAML:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="1000" Loaded="Window_Loaded">
<Window.Resources>
<local:adventuretime x:Key="adventuretime"/>
<CollectionViewSource x:Key="monstersViewSource" Source="{Binding Monsters, Source={StaticResource adventuretime}}"/>
</Window.Resources>
<Grid DataContext="{StaticResource monstersViewSource}">
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="22" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="972"/>
<DataGrid x:Name="monstersDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding}" Margin="10,37,10,10" RowDetailsVisibilityMode="VisibleWhenSelected">
<DataGrid.Columns>
<DataGridTextColumn x:Name="monsterIDColumn" Binding="{Binding MonsterID}" Header="Monster ID" IsReadOnly="True" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="nameColumn" Binding="{Binding Name}" Header="Name" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="sizeColumn" Binding="{Binding Size}" Header="Size" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="monstertypeColumn" Binding="{Binding Monstertype}" Header="Monstertype" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="alignmentColumn" Binding="{Binding Alignment}" Header="Alignment" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="aCColumn" Binding="{Binding AC}" Header="AC" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="hPColumn" Binding="{Binding HP}" Header="HP" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="strengthColumn" Binding="{Binding Strength}" Header="Strength" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="dexterityColumn" Binding="{Binding Dexterity}" Header="Dexterity" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="constitutionColumn" Binding="{Binding Constitution}" Header="Constitution" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="intelligenceColumn" Binding="{Binding Intelligence}" Header="Intelligence" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="wisdomColumn" Binding="{Binding Wisdom}" Header="Wisdom" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="charismaColumn" Binding="{Binding Charisma}" Header="Charisma" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="savesColumn" Binding="{Binding Saves}" Header="Saves" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="skillColumn" Binding="{Binding Skill}" Header="Skill" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="immuneColumn" Binding="{Binding Immune}" Header="Immune" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="sensesColumn" Binding="{Binding Senses}" Header="Senses" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="languagesColumn" Binding="{Binding Languages}" Header="Languages" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="passiveColumn" Binding="{Binding Passive}" Header="Passive" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="speedColumn" Binding="{Binding Speed}" Header="Speed" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="crColumn" Binding="{Binding cr}" Header="cr" Width="SizeToHeader"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
C#:
public partial class MainWindow : Window
{
adventuretime adventuretime;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
adventuretime = ((adventuretime)(this.FindResource("adventuretime")));
// Load data into the table Monsters. You can modify this code as needed.
adventuretimeTableAdapters.MonstersTableAdapter adventuretimeMonstersTableAdapter = new adventuretimeTableAdapters.MonstersTableAdapter();
adventuretimeMonstersTableAdapter.Fill(adventuretime.Monsters);
CollectionViewSource monstersViewSource = ((CollectionViewSource)(this.FindResource("monstersViewSource")));
monstersViewSource.View.MoveCurrentToFirst();
}
}
应用程序加载,并且我从表中获取数据,所以很棒。
我只是不知道如何操作其中的数据。
做类似dataGrid.ItemSource = linq查询的事情似乎不是一个选择。 所以我不确定如何绑定它,所以我可以过滤文本框内容。
谁能指出我正确的方向? 我一直在寻找最近两天,但是当我将数据网格拖放到WPF设计器时,似乎与我的应用程序生成的内容不匹配
CollectionViewSource.View具有一个Predicate <object>的Filter属性。 用它来过滤。
要将其绑定到您的文本框中,假设您想对“名称”进行过滤,请将事件处理程序添加到TextChanged事件的文本框中。 像这样:
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="22" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="972"
TextChanged="TextBox_TextChanged" />
在后面的代码中,添加TextBox_TextChanged方法。 定义如下:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = sender as TextBox;
CollectionViewSource monstersViewSource = ((CollectionViewSource)(this.FindResource("monstersViewSource")));
if (tb == null || string.IsNullOrWhiteSpace(tb.Text))
{
monstersViewSource.View.Filter = null;
return;
}
else
{
string txt = tb.Text;
monstersViewSource.View.Filter = item =>
{
Monster m = item as Monster;
if (m != null)
{
if (!string.IsNullOrWhiteSpace(m.Name) && m.Name.Contains(txt))
return true;
}
return false;
};
}
}
筛选器使用包含而不是等于,因此它将筛选出所有不包含文本框文本的内容。 像“ dra”将匹配“ dragon”和“ drake”。
顺便说一句-我在这个问题上看不到任何实体框架。
编辑:
我猜DataTable不支持那样的筛选。 您可能需要将DataSet1更改为您的DataSet。 也许在LIKE语句中占*的%?
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = sender as TextBox;
CollectionViewSource monstersViewSource = ((CollectionViewSource)(this.FindResource("monstersViewSource")));
if (tb == null || string.IsNullOrWhiteSpace(tb.Text))
{
DataSet1.MonstersDataTable dt = monstersViewSource.Source as DataSet1.MonstersDataTable;
dt.DefaultView.RowFilter = null;
return;
}
else
{
string txt = tb.Text;
DataSet1.MonstersDataTable dt = monstersViewSource.Source as DataSet1.MonstersDataTable;
dt.DefaultView.RowFilter = string.Format("Name LIKE '%{0}%'", txt);
}
}
编辑2:
这更快吗?
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
var tb = sender as TextBox;
CollectionViewSource monstersViewSource = ((CollectionViewSource)(this.FindResource("monstersViewSource")));
if (tb == null || string.IsNullOrWhiteSpace(tb.Text))
{
var cv = monstersViewSource.View as BindingListCollectionView;
cv.CustomFilter = null;
}
else
{
string txt = tb.Text;
var cv = monstersViewSource.View as BindingListCollectionView;
cv.CustomFilter = string.Format("Name like '%{0}%'", txt);
}
}
如果没有更快的速度,我认为您可能需要实际使用实体框架和第一个TextBox_TextChanged方法来代替数据集,数据适配器和数据表,以使其能够更快地进行过滤。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.