Задать вопрос

Как правильно сделать привязку данных в wpf?

Суть проблема такова. Имеется ListView элементами TextBox и список объектов List. Можно ли в WPF так сделать привязку, что бы не только элементы списка менялись при редактировании TextBox, но и при изменении элементов списка результат сразу бы отображался на экране? Спасибо.
  • Вопрос задан
  • 9331 просмотр
Подписаться 5 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 4
ad1Dima
@ad1Dima
ObservableCollection уведомляет о изменении своих элементов. Но и каждый элемент должен уведомлять о своем изменении, если у него меняются поля (вот тут и может пригодиться INotifyPropertyChanged)
Ответ написан
@segment
Можно. Для этого необходимо использовать интерфейс INotifyPropertyChanged. А вот пример на русском.
Ответ написан
AxisPod
@AxisPod
Как выше INotifyPropertyChanged, либо ObservableCollection, который в свою очередь реализует INotifyPropertyChanged. Ну и в binding надо указать Mode=TwoWay.

Еще такой момент, если используется ObservableCollection, то в данном случае публичным есть только событие CollectionChanged, вы получите перерисовку всего ListView, если же у вас будет пара тысяч строк, вы получите неслабый такой тормоз, тут надо будет использовать виртуальность. Но так как это всё же ListView, то INotifyPropertyChanged вам ничем не поможет.
Ответ написан
@Voucik
вот пример.
WPF форма, где у нас два контрола: ComboBox - cmb и TextBox - tb
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="<a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation</a>"
        xmlns:x="<a href="http://schemas.microsoft.com/winfx/2006/xaml">http://schemas.microsoft.com/winfx/2006/xaml</a>"
        xmlns:wpfApplication1="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ResourceDictionary>
            <wpfApplication1:ConverterNull x:Key="ConverterNull"/>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        
        <Grid.RowDefinitions>
            <RowDefinition Height="30"></RowDefinition>
            <RowDefinition Height="5"></RowDefinition>
            <RowDefinition Height="30"></RowDefinition>
        </Grid.RowDefinitions>

        <ComboBox Name ="cmb" DisplayMemberPath="Value" SelectedValuePath = "id" ></ComboBox>

        <TextBox Name="tb" Grid.Row="2"  Text="{Binding ElementName=cmb, Path=SelectedItem.Value,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,Converter={StaticResource ConverterNull}}"></TextBox>
    </Grid>
</Window>

DisplayMemberPath="Value" - то что будет отображаться (значение)
SelectedValuePath = "id" - ключ

Text="{Binding ElementName=cmb,
Path=SelectedItem.Value - поле нашего объекта, значение которого будет присваиваться нашему tb
,Mode=TwoWay, - означает, привязка на read и write (при этом у поля, нашего объекта, должен быть открыт set )
UpdateSourceTrigger=PropertyChanged - ну и фичя которая отвечает, за update данных
,Converter={StaticResource ConverterNull - а тут добавляем ещё конвертер, дабы у нас обрабатывались пустые значения.
}}"

Для этого надо добавить конвертер в ресурсы (как тут)
<Window.Resources>
        <ResourceDictionary>
            <wpfApplication1:ConverterNull x:Key="ConverterNull"/>
        </ResourceDictionary>
    </Window.Resources>


ну и путь указать к самому классу конвертера
xmlns:wpfApplication1="clr-namespace:WpfApplication1"

А теперь сам код.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        private List<Info> info;
        public MainWindow()
        {
            InitializeComponent();
            info = new List<Info>
            {
                new Info("a"),
                new Info("b"),
                new Info("c")
            };

            cmb.ItemsSource = info;
        }
    }

    public class Info
    {
        public Guid id { get; private set; }
        public string Value { get; set; }

        public Info(String val)
        {
            id = Guid.NewGuid();
            Value = val;
        }
    }

    sealed class ConverterNull : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value == null ? null : String.IsNullOrWhiteSpace(value.ToString()) ? null : value;
        }
    }
}


public class Info - наши данные
sealed class ConverterNull : IValueConverter - конвертер
присваиваем наши данные комбоБоксу cmb.ItemsSource = info;
и всё.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы