Связывание данных с WPF - Обновление CollectionViewSource при вводе - PullRequest
0 голосов
/ 26 мая 2011

Я создал образец проекта, следуя инструкциям этого MSDN Walktrough .Я немного изменил образец и создал два дополнительных элемента управления TextBox и кнопку.

Вот как это выглядит: enter image description here

Сначала я создал простую модель с использованием кодаподход и производный класс DbContext как элемент генерации кода.

После этого я использовал созданные источники данных: enter image description here

«Имя» - TextBox - ReadOnly.Я хочу разрешить пользователю вводить идентификатор и искать его, когда нажата кнопка «Поиск».Таким образом, «Имя» - TextBox должно быть обновлено, если указанный идентификатор может быть найден.Меня не волнует DataGrids, потому что они мне не нужны в моем реальном коде.

Я понятия не имею, как я могу обновить CollectionViewSource и проверить входные данные, потому что CollectionViewSource.ViewСвойство .CurrentItem доступно только для чтения.

EDIT : Это мой (почти полностью сгенерированный дизайнером) код:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" mc:Ignorable="d"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:my="clr-namespace:SchoolModel;assembly=SchoolModel" 
        Loaded="Window_Loaded">

    <Window.Resources>
        <CollectionViewSource x:Key="departmentViewSource" d:DesignSource="{d:DesignInstance my:Department, CreateList=True}" />
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Grid DataContext="{StaticResource departmentViewSource}" Name="grid1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Label Content="Department ID:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="departmentIDTextBox" Text="{Binding Path=DepartmentID, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
        </Grid>
        <Grid Grid.Row="1" DataContext="{StaticResource departmentViewSource}" Name="grid2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Label Content="Name:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="nameTextBox" Text="{Binding Path=Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
        </Grid>
    </Grid>
</Window>


public partial class MainWindow : Window
{
    private SchoolEntities _context = new SchoolEntities(@"data source=localhost\MSSQL2008R2;database=SchoolModel;integrated security=True;MultipleActiveResultSets=True");
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        System.Windows.Data.CollectionViewSource departmentViewSource =
            ((System.Windows.Data.CollectionViewSource)(this.FindResource("departmentViewSource")));

        // Load is an extension method on IQueryable, defined in the System.Data.Entity namespace.
        // This method enumerates the results of the query, much like ToList but without creating a list. 
        // When used with Linq to Entities this method creates the entity instances and adds to the context.
        _context.Departments.Load(); // Load is defined in the System.Data.Entity namespace.      

        // After the data is loaded call the DbSet<T>.Local property to use the DbSet<T> as a binding source. 
        departmentViewSource.Source = _context.Departments.Local;

        var src = _context.Departments.Local;
        ICollectionView colelctionView = CollectionViewSource.GetDefaultView(src);
        colelctionView.Filter = new Predicate<object>(i => (i as Department).DepartmentID.ToString() == departmentIDTextBox.Text);
    }
}

Ответы [ 2 ]

1 голос
/ 28 мая 2011

@ Freeze2046

ICollectionView предоставляет следующие методы для установки текущего элемента:

  • MoveCurrentToFirst
  • MoveCurrentToLast
  • MoveCurrentToNext
  • MoveCurrentToPrevious
  • MoveCurrentTo (значение объекта)

Обычно последний метод наиболее полезен для производственного кода, в котором я хочу работать с выбранным элементом

    public Department SelectedItem
    {
        get { return _collectionView.CurrentItem as Department; }
        set { _collectionView.MoveCurrentTo(value); }
    }

Он также предоставляет событие CurrentChanged, которое вы можете использовать для установки обработчика, где вы можете делать все, что вам нужно (включая проверку), чтобы реагировать на текущий изменяемый элемент.

// retrieve the ICollectionView associated with the ObservableCollection
_collectionView = CollectionViewSource.GetDefaultView(src);
if (_collectionView == null) throw new NullReferenceException("_collectionView");

//listen to the CurrentChanged event to be notified when the selection changes
_collectionView.CurrentChanged += OnCollectionViewCurrentChanged;

private void OnCollectionViewCurrentChanged(object sender, EventArgs e) {
    // whatever
}

Я мог бы сказать больше о фильтрации, но я предполагаю, что вы просто пытаетесь проработать некоторый пример кода и застряли на том, как установить CurrentItem и реагировать на него. Надеюсь, это даст вам некоторые идеи относительно того, как это сделать, но не стесняйтесь задавать больше вопросов, если вам нужно.

Приветствия
Berryl

0 голосов
/ 26 мая 2011

Ваш SearchTextBox должен быть привязан к полю SearchText в ViewModel, а не к имени CurrentItem

Ваш ViewModel должен выглядеть следующим образом:

ObservableCollection<Courses> { get; set; }
ObservableCollection<Departments> { get; set; }

string SearchText { get; set; }
ICommand SearchCommand { get; }
...