DataGrid文本框过滤不起作用

问题描述 投票:0回答:1

我有DataGrid文本框过滤的问题,因为我改变了我的方式。

有很大的ViewModel,这个实例是在应用程序初始化期间在MainWindow中创建的。

public MainWindow()
{
    InitializeComponent();
    ...
    viewModel = new ViewModel();
    viewModel.Recipients = GetRecipients();
    ...
}

我不知道这是不是很好的方法,但对我来说这是有效的,所以我坚持这一点。我正在这样做,因为我想在程序启动时从数据库加载一次大数据,所以其他元素可以在整个时间使用它。 GetRecipients就是用来做的。

这就是我的ViewModel(重要部分)的样子:

public class ViewModel : INotifyPropertyChanged
{

    private ICollectionView recipientsView;

    private CultureInfo culture;

    private ICommand _command;

    private ObservableCollection<Recipient> _recipients;

    public ObservableCollection<Recipient> Recipients
    {
        get { return _recipients; }
        set
        {
            _odbiorcy = value;
            OnPropertyChanged("Recipients");
        }
    }

    private bool _isEmpty;

    public bool IsEmpty
    {
        get { return _isEmpty; }
        set
        {
            _isEmpty = value;
            OnPropertyChanged("IsEmpty");
        }
    }

    private string _filter;

    public string Filter
    {
        get { return _filter; }
        set
        {
            _filter = value;
            recipientsView.Refresh();
            OnPropertyChanged("Filter");
        }
    }

    private Recipient_selected;

    public Recipient Selected
    {
        get { return _selected; }
        set
        {
            _selected = value;
            OnPropertyChanged("Selected");
        }
    }



    public ViewModel()
    {
        Recipients = new ObservableCollection<Recipient>();
        recipientsView= CollectionViewSource.GetDefaultView(Recipients);
        recipientsView.Filter = o => String.IsNullOrEmpty(Filter) ? true : ((Recipient)o).Name.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0 ||
                                                                         ((Recipient)o).City.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0 ||
                                                                         ((Recipient)o).Street.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0 ||
                                                                         ((Recipient)o).PostCode.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0 ||
                                                                         ((Recipient)o).ContactPerson.IndexOf(Filter, StringComparison.OrdinalIgnoreCase) >= 0;
    }




    public void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

}

和...

Recipients.xaml

<UserControl x:Class="DHL.Recipients"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:DHL"
         mc:Ignorable="d" 
         d:DesignHeight="460" d:DesignWidth="750">
<Grid Background="White">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="0">
        <Grid.RowDefinitions>
            <RowDefinition Height="60" />
            <RowDefinition Height="350"/>
            <RowDefinition Height="50" />
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Label Content="Search recipient:" Margin="25,0,0,0"></Label>
            <TextBox x:Name="FilterTextBox" Text="{Binding Filter, UpdateSourceTrigger=PropertyChanged}" Width="145" Height="25" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="25,25,0,0"/>
        </Grid>
        <Grid Grid.Row="1">
            <DataGrid IsReadOnly="True" x:Name="RecipientsGrid" AutoGenerateColumns="False" EnableRowVirtualization="True"
                      EnableColumnVirtualization="True" ItemsSource="{Binding Recipients}" Height="350" VerticalAlignment="Bottom"
                      SelectedItem="{Binding Selected,Mode=TwoWay}"
                      HorizontalScrollBarVisibility="Visible" MouseDoubleClick="Row_DoubleClick">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Name" Width="250" Binding="{Binding Name,UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="Street" Width="150" Binding="{Binding Street,UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="House Number" Width="150" Binding="{Binding HouseNumber,UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="Apartament Number" Width="150" Binding="{Binding ApartamentNumber,UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="Postal Code" Width="150" Binding="{Binding PostalCode,UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="City" Width="150" Binding="{Binding City,UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="Contact Person" Width="150" Binding="{Binding ContactPerson, UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="Email" Width="150" Binding="{Binding Email, UpdateSourceTrigger=PropertyChanged}"/>
                    <DataGridTextColumn Header="Phone Number" Width="150" Binding="{Binding PhoneNumber, UpdateSourceTrigger=PropertyChanged}"/>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
        <Grid Grid.Row="2">
            <Button x:Name="CloseButton" Click="CloseButton_Click"
                    VerticalAlignment="Bottom" Margin="0,0,0,10" Width="100" Height="25" Content="Close"></Button>
        </Grid>
    </Grid>
</Grid>

Recipients类:

public partial class Recipients : UserControl
{

    ViewModel viewModel;

    public Recipients (ViewModel model)
    {
        InitializeComponent();
        this.viewModel = model;
        this.DataContext = viewModel;
    }

    public Recipients ()
    {
        InitializeComponent();
        ViewModel view = new ViewModel();
        this.DataContext = view;
    }

    private void CloseButton_Click(object sender, RoutedEventArgs e)
    {
        var parent = this.Parent as Window;

        if (parent != null)
        {
            parent.DialogResult = true;
            parent.Close();
        }
    }

    private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
    {
        CloseButton_Click(this, null);
    }
}

我试图以两种方式创建新的Recipients实例(在参数中使用ViewModel而没有它)。在我改变整个项目之后,两者都停止了工作(创建ViewModel实例一次并在项目的每个地方使用它 - 还有一部分我还在努力处理)。我认为这可能有用,因为PropertyChanged但似乎我错了。

问题是:这是创建ViewModel一次的好方法,而不是在我想要使用的每个UserControl中创建ViewModel吗?如果是的话,我的代码出了什么问题?

c# wpf data-binding
1个回答
1
投票

我的代码出了什么问题

你过滤错误的收藏。 这里是最初创建集合及其视图的位置:

public ViewModel()
{
    Recipients = new ObservableCollection<Recipient>();
    recipientsView= CollectionViewSource.GetDefaultView(Recipients);

    // rest of code not shown
}

然后,您要为集合分配新实例:

// MainWindow ctor
viewModel.Recipients = GetRecipients();

您的网格绑定到集合,而不是其视图,集合最终包含GetRecipients的结果:

ItemsSource="{Binding Recipients}"

要解决此问题,请执行以下操作:

1)修复数据绑定。将网格绑定到集合视图,而不是集合本身:

// view model
public ICollectionView RecipientsView
{ 
    get
    {
        if (recipientsView == null)
        {
            // DO NOT create collection view inside constructor
            recipientsView = CollectionViewSource.GetDefaultView(Recipients);
            recipientsView.Filter = // filtering code here;
        }

        return recipientsView;
    }
}

<!-- DataGrid XAML -->
ItemsSource="{Binding RecipientsView}"

2)让Recipients得到唯一。通常,您不需要在视图模型中更改集合对象引用。您需要更改收藏内容:

public ObservableCollection<Recipient> Recipients
{
    get
    {
        if (_recipients == null)
        {
            // DO NOT create collection inside constructor
            _recipients = new ObservableCollection<Recipient>();          
        }

        return _recipients;
    }
}

3)更改收集人口代码。添加UpdateRecipients方法来查看模型:

   public void UpdateRecipients(IEnumerable<Recipient> newRecipients)
   {
       Recipients.Clear();

       foreach (var item in newRecipients)
       {
           Recipients.Add(item);
       }
   }

并在初始化时调用它:

viewModel = new ViewModel();
viewModel.UpdateRecipients(GetRecipients());
© www.soinside.com 2019 - 2024. All rights reserved.