Why Binding works unpredictable?

Fomin Dmitry

I create a control (let's it be listViewEx) with two custom dependency properties: SelectedItem, ItemsSource. This control is derived from ContentControl and have Content property set to ListView instance.

listViewEx have next bindings:

listViewEx.SelectedItem -> ListView.SelectedItem, listViewEx.ItemsSource -> ListView.ItemsSource

now i got a form, with two combo boxes (box1 and box2) and one listViewEx, Form has next bindings:

box1.SelectedItem -> SelectedPerson, box1.ItemsSource -> Persons

box2.SelectedItem -> SelectedPerson, box2.ItemsSource -> Persons

listViewEx.SelectedItem -> SelectedPerson, listViewEx.ItemsSource -> Persons

form has a valid DataContext value with corresponding SelectedPerson and Persons properties and values.

Now the question: why every bindings works fine except this one:

listViewEx.SelectedItem -> SelectedPerson

If i change values in combo boxes - than selection chaged in listViewEx until i change selection in ListViewEx, after that combo boxes works fine, but listViewEx loses every bindings. What i'm doing wrong?

Problem reproduction video (gif)

listViewEx code:

public class ListViewEx : ContentControl
{
    ListView list = new ListView();

    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ItemsSource.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(ListViewEx), new UIPropertyMetadata(null));


    public object SelectedItem
    {
        get { return (object)GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    // Using a DependencyProperty as the backing store for SelectedItem.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(object), typeof(ListViewEx), new UIPropertyMetadata(null));

    public ListViewEx()
    {
        Content = list;
        list.SetBinding(ListView.SelectedItemProperty, "SelectedItem");
        list.SetBinding(ListView.ItemsSourceProperty, "ItemsSource");
        list.DataContext = this;
    }
}

Form code:

public partial class MainWindow : Window
{
    Data data;
    public MainWindow()
    {
        InitializeComponent();
        data = new Data
        {
            Persons = new[] { 
                new Person{ Age=11, Name="Ivan"}, 
                new Person{ Age=10, Name="Petr"}, 
                new Person{ Age=20, Name="Masha"}, 
                new Person{ Age=30, Name="Dasha"}, 
                new Person{ Age=40, Name="Gennadiy"}, 
                new Person{ Age=50, Name="Viktor"}, 
                new Person{ Age=90, Name="Victory!"}, 
            }
        };

        DataContext = data;
    }

    class Data
    {
        public Person[] Persons { get; set; }
        public object SelectedPerson { get; set; }
    }

    class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }
        public override string ToString()
        {
            return Name;
        }
    }
}

Form XAML:

<Window x:Class="DependencyPropertyTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DependencyPropertyTest"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <ComboBox ItemsSource="{Binding Persons}" SelectedItem="{Binding SelectedPerson}"></ComboBox>
    <ComboBox ItemsSource="{Binding Persons}" SelectedItem="{Binding SelectedPerson}"></ComboBox>
    <local:ListViewEx ItemsSource="{Binding Persons}" SelectedItem="{Binding SelectedPerson}" Height="400"></local:ListViewEx>
</StackPanel>

Clemens

The SelectedItem property of your ListViewEx control should be bound two-way, either by writing

<local:ListViewEx SelectedItem="{Binding SelectedPerson, Mode=TwoWay}" ... />

or by declaring it as binding two-way by default:

public static readonly DependencyProperty SelectedItemProperty =
    DependencyProperty.Register(
        "SelectedItem",
        typeof(object),
        typeof(ListViewEx),
        new FrameworkPropertyMetadata(
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related