我有一个名为QtyControl的用户控件,带有一个名为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); }
}
}
}