0

我有一个名为 QtyControl 的数量的 UserControl,以及一个名为 Qty(一个 int)的 DependencyProperty。我正在使用 注册此属性DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,但如果我不设置UpdateSourceTrigger=PropertyChanged控件使用者的绑定,它就不起作用,我不明白为什么。

该代码应允许您单击“添加”按钮并查看您在组合框中选择的任何数字,但始终显示 0。

MainWindow.xaml:

<Window x:Class="UserControlTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:UserControlTest"
        Title="MainWindow" Height="150" Width="250"
        WindowStartupLocation="CenterScreen">
  <StackPanel>
    <DataGrid ItemsSource="{Binding MyItems}"
              IsReadOnly="True"
              Height="Auto" Width="Auto"
              HeadersVisibility="Column"
              AutoGenerateColumns="False"
              SelectionMode="Single">
      <DataGrid.Columns>
        <DataGridTemplateColumn Header="Qty" Width="50">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <local:QtyControl Qty="{Binding QtyRequested}" /> <!--, UpdateSourceTrigger=PropertyChanged - this is needed, but I don't know why when I registered Qty with DefaultUpdateSourceTrigger=PropertyChanged -->
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Add" Width="50">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <Button Click="_AddItemBtn_Click">Add</Button>
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
      </DataGrid.Columns>
    </DataGrid>
  </StackPanel>
</Window>

MainWindow.xaml.cs:

using System.Windows.Controls;
using System.Windows.Media;

namespace UserControlTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MyViewModel();
        }

        private void _AddItemBtn_Click(object sender, RoutedEventArgs e)
        {
            DataGridRow parentRow = _FindDataGridRowFromCl((Control)sender);
            MyItem item = (MyItem)parentRow.Item;
            MessageBox.Show($"QtyRequested = {item.QtyRequested}");
        }

        private DataGridRow _FindDataGridRowFromCl(Control cl)
        {
            for (Visual vi = cl as Visual; vi != null; vi = VisualTreeHelper.GetParent(vi) as Visual)
                if (vi is DataGridRow row)
                    return row;
            return null;
        }
    }

    public class MyItem
    {
        public int QtyRequested { get; set; } = 0;
    }

    public class MyViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<MyItem> _myItems;
        public ObservableCollection<MyItem> MyItems {
            get {
                return _myItems;
            }
            set {
                _myItems = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyItems)));
            }
        }

        public MyViewModel()
        {
            MyItems = new ObservableCollection<MyItem> { new MyItem() };
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

QtyControl.xaml:

<UserControl x:Class="UserControlTest.QtyControl"
             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" 
             xmlns:local="clr-namespace:UserControlTest"
             mc:Ignorable="d" Height="22" Width="42"
             >
  <Grid>
    <ComboBox Name="_comboBox"
              SelectedIndex="{Binding Qty, RelativeSource={RelativeSource AncestorType=UserControl}}">
      <ComboBox.Items>
        <ComboBoxItem Content="0" IsSelected="True" />
        <ComboBoxItem Content="1" />
        <ComboBoxItem Content="2" />
      </ComboBox.Items>
    </ComboBox>
  </Grid>
</UserControl>

QtyControl.xaml.cs:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace UserControlTest
{
    public partial class QtyControl : UserControl
    {
        public QtyControl()
        {
            InitializeComponent();
        }

        public static DependencyProperty QtyProperty;

        static QtyControl()
        {
            QtyProperty = DependencyProperty.Register(
                "Qty",
                typeof(int),
                typeof(QtyControl),
                new FrameworkPropertyMetadata(
                    defaultValue: 1,
                    flags: FrameworkPropertyMetadataOptions.AffectsArrange,
                    propertyChangedCallback: null,
                    coerceValueCallback: null,
                    isAnimationProhibited: false,
                    defaultUpdateSourceTrigger: UpdateSourceTrigger.PropertyChanged
                    )
                /* Also does not work
                new FrameworkPropertyMetadata(
                    1,
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault
                    )
                */
                );
        }

        public int Qty
        {
            get { return (int)GetValue(QtyProperty); }
            set { SetValue(QtyProperty, value);  }
        }
    }
}
4

0 回答 0