A
A
Andrew2013-10-06 23:16:57
.NET
Andrew, 2013-10-06 23:16:57

How to properly bind data in wpf?

The essence of the problem is this. There is a ListView with TextBox elements and a list of List objects. Is it possible in WPF to make the binding so that not only the list items change when the TextBox is edited, but also when the list items change, the result would immediately be displayed on the screen? Thank you.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
A
ad1Dima, 2013-10-07
@ad1Dima

ObservableCollection notifies when its elements change. But each element must also notify of its change if its fields change (this is where INotifyPropertyChanged can come in handy)

S
Sergey, 2013-10-07
@segment

Can. To do this, you must use the INotifyPropertyChanged interface . And here is an example in Russian.

A
AxisPod, 2013-10-07
@AxisPod

Like INotifyPropertyChanged above, or an ObservableCollection which in turn implements INotifyPropertyChanged. Well, in the binding you need to specify Mode=TwoWay.
Another such moment, if ObservableCollection is used, then in this case only the CollectionChanged event is public, you will get a redrawing of the entire ListView, but if you have a couple of thousand rows, you will get such a strong brake, here you will need to use virtuality. But since it's still a ListView, INotifyPropertyChanged won't help you.

V
Voucik, 2013-11-19
@Voucik

here is an example.
WPF form where we have two controls: ComboBox - cmb and 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" - what will be displayed (value)
SelectedValuePath = "id" - key
Text="{Binding ElementName=cmb,
Path=SelectedItem.Value - field of our object, the value of which will be assigned to our tb
,Mode=TwoWay, - means binding to read and write (at the same time, set must be open for the field, our object)
UpdateSourceTrigger=PropertyChanged - well, the feature that is responsible for updating data
,Converter={StaticResource ConverterNull - and here we add another converter we were processing empty values.
}}"
To do this, you need to add a converter to the resources (as here)
<Window.Resources>
        <ResourceDictionary>
            <wpfApplication1:ConverterNull x:Key="ConverterNull"/>
        </ResourceDictionary>
    </Window.Resources>

well, specify the path to the converter class itself
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
And now the code itself.
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 - our data is
sealed class ConverterNull : IValueConverter - the converter
assigns our data to the comboBox cmb.ItemsSource = info;
and that's it.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question