首页 > 解决方案 > 将用户控件绑定到 DataGrid 中的数据

问题描述

我有一个Dependency Property用于绑定数据的小问题;

我有一个用户控件,其中包含一个textBox. 我创建了一个DataGrid,我在其中添加了usercontrol它的一列。然后我使用dataContext进行了绑定。

当我第一次运行应用程序时,用户控件充满了数据(在我的情况下,数据绑定到特定字段“名称”),但是当我修改值时,新值没有写入,它仍然保留旧值。

TT.xaml.cs

namespace WPF_Prj.View
{
    public partial class TT : UserControl
    {
        public float MyText
        {
            get { 
                return (float)GetValue(MyTextProperty); 
            }
            set { 
                SetValue(MyTextProperty, value ); 
            }
        }

    public static readonly DependencyProperty MyTextProperty =
        DependencyProperty.Register("MyText", typeof(float), typeof(TT), new FrameworkPropertyMetadata(null) { BindsTwoWayByDefault = true });

    public TT()
    {
        InitializeComponent();
    }
}

}

TT.xaml

<UserControl x:Class="WPF_Prj.View.TT"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <TextBox Height="20" Width="100" 
                Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, 
                Path=MyText, 
                UpdateSourceTrigger=PropertyChanged}">
    </TextBox>
</Grid>

主窗口.xaml

<Window x:Class="WPF_Prj.View.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"
    xmlns:local="clr-namespace:WPF_Prj.View"
    Title="[Portfolio] MainWindow" Height="500" Width="800">

<StackPanel Orientation="Vertical">

    <DataGrid x:Name="datagrid" AutoGenerateColumns="False" CanUserAddRows="False"
            Width="Auto" Margin="5,5,0,5" HorizontalAlignment="Left" CellEditEnding="datagrid_CellEndEditing">
        <DataGrid.Columns>
            <DataGridTextColumn Header=""                                                                                            IsReadOnly="True"  Width="1"/>
            <DataGridTextColumn Header="Name"           Binding="{Binding Name, Mode=TwoWay, NotifyOnTargetUpdated=True}"            IsReadOnly="True"  Width="Auto"/>
            <DataGridTextColumn Header="Owned Qty"      Binding="{Binding OwnedQty, Mode=TwoWay, NotifyOnTargetUpdated=True}"        IsReadOnly="True"  Width="Auto"/>
            <DataGridTemplateColumn Header="Ordered/Eligible">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <local:TT x:Name="test" MyText="{Binding OwnedQty, Mode=TwoWay}"></local:TT>
                    </DataTemplate> 
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    </StackPanel>

在 mainWindow.xaml.cs 我从一个ViewModel实现的类中获取数据,ObservableCollection而模型是一个实现的类INotifyPropertyChanged

所以在下图中:绿色框是从我的数据库加载到网格的内容,红色是我的用户控件,它保存和编辑,起初它包含加载的值,但是当我将它更改为其他值时,绿色中的值仍然不变。

在此处输入图像描述

标签: wpfdata-binding

解决方案


这为我修复了它。你不需要Mode=TwoWay;在依赖属性定义中已经是默认的了。您确实需要UpdateSourceTrigger=PropertyChanged,无论是否在 DP 定义中。

<DataTemplate>
    <local:TT 
        x:Name="test" 
        MyText="{Binding OwnedQty, UpdateSourceTrigger=PropertyChanged}"
        ></local:TT>
</DataTemplate>

我希望能够通过DefaultUpdateSourceTrigger在 Dependency Property 定义中进行初始化来做同样的事情,但这不会产生相同的效果。我不知道为什么会这样。

请注意,我还将默认值更改为0F; null会抛出异常。

public static readonly DependencyProperty MyTextProperty =
    DependencyProperty.Register("MyText", typeof(float), typeof(TT), 
        new FrameworkPropertyMetadata(0F) {
            BindsTwoWayByDefault = true
            //  Nope. 
            //, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
        });

这是我的视图模型属性。我正在设置一个断点OnPropertyChanged()来检测绑定何时更新属性。

private float _ownedQty = 0F;
public float OwnedQty
{
    get { return _ownedQty; }
    set
    {
        if (value != _ownedQty)
        {
            _ownedQty = value;
            OnPropertyChanged();
        }
    }
}

推荐阅读