Two way data binding in a GridView

余生颓废 提交于 2019-12-12 18:20:45

问题


We have an app that uses simple one way binding with a GridView to display some data. Well, now we need to allow the user to change some of that data, so I've been trying to get two way data binding to work in the GridView. So far everything displays correctly, but editing cells in the GridView seems to do nothing at all. What am I messing up? Is two way databinding like this even possible? Should I just start converting everything to use a different control, like maybe a DataGrid?

I wrote a tiny test app that shows my problem. If you try it, you'll see that the property setters never get called after their initialization.

Xaml:

    Title="Window1" Height="300" Width="300">
    <Grid>
        <ListView Name="TestList">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Strings">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBox Text="{Binding Path=String, Mode=TwoWay}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Bools">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox IsChecked="{Binding Path=Bool, Mode=TwoWay}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

And here's the corresponding code:

using System.Collections.Generic;
using System.Windows;

namespace GridViewTextbox
{
    public partial class Window1 : Window
    {
        private List<TestRow> _rows = new List<TestRow>();

        public Window1()
        {
            InitializeComponent();

            _rows.Add(new TestRow("a", false));
            _rows.Add(new TestRow("b", true));
            _rows.Add(new TestRow("c", false));

            TestList.ItemsSource = _rows;
            TestList.DataContext = _rows;
        }
    }

    public class TestRow : System.Windows.DependencyObject
    {
        public TestRow(string s, bool b)
        {
            String = s;
            Bool = b;
        }

        public string String
        {
            get { return (string)GetValue(StringProperty); }
            set { SetValue(StringProperty, value); }
        }

        // Using a DependencyProperty as the backing store for String.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StringProperty =
            DependencyProperty.Register("String", typeof(string), typeof(TestRow), new UIPropertyMetadata(""));


        public bool Bool
        {
            get { return (bool)GetValue(BoolProperty); }
            set { SetValue(BoolProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Bool.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BoolProperty =
            DependencyProperty.Register("Bool", typeof(bool), typeof(TestRow), new UIPropertyMetadata(false));
    }
}

回答1:


When you use Dependency Properties, the Setters will not be called by bindings, instead they change the value directly (using SetValue or something similar).

Try adding a PropertyChangedCallback, and set a breakpoint in there to see if the value is changed from the GridView.

public static readonly DependencyProperty BoolProperty =
    DependencyProperty.Register("Bool", typeof(bool), typeof(TestRow), new UIPropertyMetadata(false, OnBoolChanged));
private static void OnBoolChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    //this method will be called everytime Bool changes value
}



回答2:


The property setters will NOT be called from WPF if they are dependency properties. Those are used as CLR conveniences and get called by code which is not aware of DependencyProperty.

The WPF code will do:

yourControl.SetValue(TestRow.StringProperty, someValue);

Not:

yourControl.String = someValue;

You need to hook the DepedencyPropertyChanged event to hear the changes.



来源:https://stackoverflow.com/questions/504887/two-way-data-binding-in-a-gridview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!