当绑定未明确设置 UpdateSourceTrigger 时,DependencyProperty 无法在绑定内创建正确的 UpdateSourceTrigger
DependencyProperty fails to create proper UpdateSourceTrigger inside binding when the binding has not set UpdateSourceTrigger explicitly
@update - 请参阅下面的更新
我得到了 DataGridTemplateColumn
中使用的 UserControl
。当我像这样 {Binding MyProperty, UpdateSourceTrigger=PropertyChanged}
指定绑定时,它会更新源。但是我忽略了 UpdateSourceTrigger
它不会更新源代码。
DependencyProperty
是这样创建的:
public static readonly DependencyProperty RatingValueProperty = DependencyProperty.Register(
"RatingValue", typeof(int?), typeof(RatingControl), new FrameworkPropertyMetadata(default(int),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
DependencyPropertyChangedCallback,
CoerceRatingValueCallback,
false,
UpdateSourceTrigger.PropertyChanged
));
正如您在下面看到的,当省略 UpdateSourceTrigger
时,Binding
是使用 Default
标志创建的,如果没有,则使用 PropertyChanged
标志创建。
"not working" 绑定(参见两个示例的第 26 行):
0 _binding {System.Windows.Data.Binding} System.Windows.Data.BindingBase {System.Windows.Data.Binding}
1 AsyncState null object
2 BindingGroupName "" string
3 BindsDirectlyToSource false bool
4 Converter null System.Windows.Data.IValueConverter
5 ConverterCulture null System.Globalization.CultureInfo
6 ConverterCultureInternal null System.Globalization.CultureInfo
7 ConverterParameter null object
8 Delay 0 int
9 ElementName null string
10 FallbackValue {{DependencyProperty.UnsetValue}} object {MS.Internal.NamedObject}
11 Flags Default System.Windows.Data.BindingBase.BindingFlags
12 IsAsync false bool
13 Mode Default System.Windows.Data.BindingMode
14 NotifyOnSourceUpdated false bool
15 NotifyOnTargetUpdated false bool
16 NotifyOnValidationError false bool
17 Path {System.Windows.PropertyPath} System.Windows.PropertyPath
18 RelativeSource null System.Windows.Data.RelativeSource
19 Source null object
20 SourceReference null MS.Internal.Data.ObjectRef
21 StringFormat null string
22 TargetNullValue {{DependencyProperty.UnsetValue}} object {MS.Internal.NamedObject}
23 TransfersDefaultValue true bool
24 TreeContextIsRequired false bool
25 UpdateSourceExceptionFilter null System.Windows.Data.UpdateSourceExceptionFilterCallback
26 UpdateSourceTrigger Default System.Windows.Data.UpdateSourceTrigger
27 ValidatesOnDataErrors false bool
28 ValidatesOnExceptions false bool
29 ValidatesOnNotifyDataErrors true bool
30 ValidatesOnNotifyDataErrorsInternal true bool
31 ValidationRules Count = 0 System.Collections.ObjectModel.Collection<System.Windows.Controls.ValidationRule> {MS.Internal.Controls.ValidationRuleCollection}
32 ValidationRulesInternal Count = 0 System.Collections.ObjectModel.Collection<System.Windows.Controls.ValidationRule> {MS.Internal.Controls.ValidationRuleCollection}
33 XPath null string
34 _attachedPropertiesInPath 0 int
35 _bindsDirectlyToSource false bool
36 _doesNotTransferDefaultValue false bool
37 _flags Default System.Windows.Data.BindingBase.BindingFlags
38 _isAsync false bool
39 _isSealed true bool
40 _ppath {System.Windows.PropertyPath} System.Windows.PropertyPath
41 _source {MS.Internal.Data.ExplicitObjectRef} MS.Internal.Data.ObjectRef {MS.Internal.Data.ExplicitObjectRef}
42 _sourceInUse None System.Windows.Data.Binding.SourceProperties
43 _values {MS.Internal.UncommonValueTable} MS.Internal.UncommonValueTable
44 Static members
"working"绑定:
0 _binding {System.Windows.Data.Binding} System.Windows.Data.BindingBase {System.Windows.Data.Binding}
1 AsyncState null object
2 BindingGroupName "" string
3 BindsDirectlyToSource false bool
4 Converter null System.Windows.Data.IValueConverter
5 ConverterCulture null System.Globalization.CultureInfo
6 ConverterCultureInternal null System.Globalization.CultureInfo
7 ConverterParameter null object
8 Delay 0 int
9 ElementName null string
10 FallbackValue {{DependencyProperty.UnsetValue}} object {MS.Internal.NamedObject}
11 Flags PropDefault | ValidatesOnNotifyDataErrors System.Windows.Data.BindingBase.BindingFlags
12 IsAsync false bool
13 Mode Default System.Windows.Data.BindingMode
14 NotifyOnSourceUpdated false bool
15 NotifyOnTargetUpdated false bool
16 NotifyOnValidationError false bool
17 Path {System.Windows.PropertyPath} System.Windows.PropertyPath
18 RelativeSource null System.Windows.Data.RelativeSource
19 Source null object
20 SourceReference null MS.Internal.Data.ObjectRef
21 StringFormat null string
22 TargetNullValue {{DependencyProperty.UnsetValue}} object {MS.Internal.NamedObject}
23 TransfersDefaultValue true bool
24 TreeContextIsRequired false bool
25 UpdateSourceExceptionFilter null System.Windows.Data.UpdateSourceExceptionFilterCallback
26 UpdateSourceTrigger PropertyChanged System.Windows.Data.UpdateSourceTrigger
27 ValidatesOnDataErrors false bool
28 ValidatesOnExceptions false bool
29 ValidatesOnNotifyDataErrors true bool
30 ValidatesOnNotifyDataErrorsInternal true bool
31 ValidationRules Count = 0 System.Collections.ObjectModel.Collection<System.Windows.Controls.ValidationRule> {MS.Internal.Controls.ValidationRuleCollection}
32 ValidationRulesInternal Count = 0 System.Collections.ObjectModel.Collection<System.Windows.Controls.ValidationRule> {MS.Internal.Controls.ValidationRuleCollection}
33 XPath null string
34 _attachedPropertiesInPath 0 int
35 _bindsDirectlyToSource false bool
36 _doesNotTransferDefaultValue false bool
37 _flags PropDefault | ValidatesOnNotifyDataErrors System.Windows.Data.BindingBase.BindingFlags
38 _isAsync false bool
39 _isSealed true bool
40 _ppath {System.Windows.PropertyPath} System.Windows.PropertyPath
41 _source {MS.Internal.Data.ExplicitObjectRef} MS.Internal.Data.ObjectRef {MS.Internal.Data.ExplicitObjectRef}
42 _sourceInUse None System.Windows.Data.Binding.SourceProperties
43 _values {MS.Internal.UncommonValueTable} MS.Internal.UncommonValueTable
44 Static members
如何解决这个问题,这样我就不必在 WPF 中显式设置 "UpdateSourceTrigger=PropertyChanged"。
@更新 2017-06-03
我已将 link (click) 附加到示例项目以说明该问题。请用第 #35-#39 行打开 MainWindow.xaml 和 fiddle。 #36 行表示不工作行为,#39 行表示工作行为。
第 36 行
<local:RatingControl StarsCount="5" RatingValue="{Binding Rating, PresentationTraceSources.TraceLevel=High}" IsReadonly="False" HorizontalContentAlignment="Center" />
第 39 行
<local:RatingControl StarsCount="5" RatingValue="{Binding Rating, UpdateSourceTrigger=PropertyChanged, PresentationTraceSources.TraceLevel=High}" IsReadonly="False" HorizontalContentAlignment="Center" />
@Edit - 请求 XAML 代码
<UserControl x:Class="so_44248130.RatingControl"
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="24" d:DesignWidth="240">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<BitmapImage x:Key="StarEmpty" UriSource="pack://application:,,,/so_44248130;component/star_black_empty.png" CacheOption="OnLoad" CreateOptions="IgnoreImageCache" />
<BitmapImage x:Key="StarFull" UriSource="pack://application:,,,/so_44248130;component/star_black_full.png" />
</UserControl.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding StarsList, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Button Grid.Row="0" Grid.Column="0" Width="24" Height="24" MaxHeight="24" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Tag="{Binding}" Padding="0" HorizontalContentAlignment="Center" Click="ButtonBase_OnClick">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Grid.Column="0" Width="{Binding EmptyStarWidth}" Height="24" HorizontalAlignment="Left">
<Rectangle.Fill>
<ImageBrush ImageSource="{StaticResource StarEmpty}"
TileMode="Tile"
Stretch="Uniform"
AlignmentY="Top"
Viewport="0,0,24,3000"
ViewportUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Row="0" Grid.Column="0" Width="{Binding FullStarWidth}" Height="24" HorizontalAlignment="Left">
<Rectangle.Fill>
<ImageBrush ImageSource="{StaticResource StarFull}"
TileMode="Tile"
Stretch="Uniform"
AlignmentY="Top"
Viewport="0,0,24,3000"
ViewportUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
</Grid>
</Button>
<Rectangle Grid.Row="0" Grid.Column="0" Height="24" Width="24" Visibility="{Binding IsReadonly, Converter={StaticResource BooleanToVisibilityConverter}}" Fill="#02FFFFFF" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
使用FrameworkPropertyMetadata
有什么具体原因吗?
如果您只是备份 属性 然后尝试使用 PropertyMetadata
.
参考here了解更多详情。
我已经弄明白了...部分...
在问题链接的示例项目中,应该导航到 RatingControl.xaml.cs
文件,行 #206-#228 (click)。这是 ButtonBase_OnClick
方法。在 if (star.Value ==
~ 部分下,我添加了绑定力 UpdateSource
。请参阅下面的代码。
if (star.Value == RatingValue)
{
RatingValue = 0;
}
else
{
RatingValue = star.Value;
}
BindingExpression binding = GetBindingExpression(RatingValueProperty);
if (binding != null)
{
binding.UpdateSource();
}
这会强制更新 BindingSource
并解决问题(这可能是某种解决方法.. 但也许它会让某人朝着正确的方向前进 post 真正有效的答案)。
注:
在调试时我检查了接收到的 BindingExpression
和名为 IsUpdateOnPropertyChanged
的 属性 由于某种原因被设置为 false
。我相信它应该设置为 true
但是我缺乏关于 WPF
内部的知识 post 它作为答案,因此 "note" 区域。
@update - 请参阅下面的更新
我得到了 DataGridTemplateColumn
中使用的 UserControl
。当我像这样 {Binding MyProperty, UpdateSourceTrigger=PropertyChanged}
指定绑定时,它会更新源。但是我忽略了 UpdateSourceTrigger
它不会更新源代码。
DependencyProperty
是这样创建的:
public static readonly DependencyProperty RatingValueProperty = DependencyProperty.Register(
"RatingValue", typeof(int?), typeof(RatingControl), new FrameworkPropertyMetadata(default(int),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
DependencyPropertyChangedCallback,
CoerceRatingValueCallback,
false,
UpdateSourceTrigger.PropertyChanged
));
正如您在下面看到的,当省略 UpdateSourceTrigger
时,Binding
是使用 Default
标志创建的,如果没有,则使用 PropertyChanged
标志创建。
"not working" 绑定(参见两个示例的第 26 行):
0 _binding {System.Windows.Data.Binding} System.Windows.Data.BindingBase {System.Windows.Data.Binding}
1 AsyncState null object
2 BindingGroupName "" string
3 BindsDirectlyToSource false bool
4 Converter null System.Windows.Data.IValueConverter
5 ConverterCulture null System.Globalization.CultureInfo
6 ConverterCultureInternal null System.Globalization.CultureInfo
7 ConverterParameter null object
8 Delay 0 int
9 ElementName null string
10 FallbackValue {{DependencyProperty.UnsetValue}} object {MS.Internal.NamedObject}
11 Flags Default System.Windows.Data.BindingBase.BindingFlags
12 IsAsync false bool
13 Mode Default System.Windows.Data.BindingMode
14 NotifyOnSourceUpdated false bool
15 NotifyOnTargetUpdated false bool
16 NotifyOnValidationError false bool
17 Path {System.Windows.PropertyPath} System.Windows.PropertyPath
18 RelativeSource null System.Windows.Data.RelativeSource
19 Source null object
20 SourceReference null MS.Internal.Data.ObjectRef
21 StringFormat null string
22 TargetNullValue {{DependencyProperty.UnsetValue}} object {MS.Internal.NamedObject}
23 TransfersDefaultValue true bool
24 TreeContextIsRequired false bool
25 UpdateSourceExceptionFilter null System.Windows.Data.UpdateSourceExceptionFilterCallback
26 UpdateSourceTrigger Default System.Windows.Data.UpdateSourceTrigger
27 ValidatesOnDataErrors false bool
28 ValidatesOnExceptions false bool
29 ValidatesOnNotifyDataErrors true bool
30 ValidatesOnNotifyDataErrorsInternal true bool
31 ValidationRules Count = 0 System.Collections.ObjectModel.Collection<System.Windows.Controls.ValidationRule> {MS.Internal.Controls.ValidationRuleCollection}
32 ValidationRulesInternal Count = 0 System.Collections.ObjectModel.Collection<System.Windows.Controls.ValidationRule> {MS.Internal.Controls.ValidationRuleCollection}
33 XPath null string
34 _attachedPropertiesInPath 0 int
35 _bindsDirectlyToSource false bool
36 _doesNotTransferDefaultValue false bool
37 _flags Default System.Windows.Data.BindingBase.BindingFlags
38 _isAsync false bool
39 _isSealed true bool
40 _ppath {System.Windows.PropertyPath} System.Windows.PropertyPath
41 _source {MS.Internal.Data.ExplicitObjectRef} MS.Internal.Data.ObjectRef {MS.Internal.Data.ExplicitObjectRef}
42 _sourceInUse None System.Windows.Data.Binding.SourceProperties
43 _values {MS.Internal.UncommonValueTable} MS.Internal.UncommonValueTable
44 Static members
"working"绑定:
0 _binding {System.Windows.Data.Binding} System.Windows.Data.BindingBase {System.Windows.Data.Binding}
1 AsyncState null object
2 BindingGroupName "" string
3 BindsDirectlyToSource false bool
4 Converter null System.Windows.Data.IValueConverter
5 ConverterCulture null System.Globalization.CultureInfo
6 ConverterCultureInternal null System.Globalization.CultureInfo
7 ConverterParameter null object
8 Delay 0 int
9 ElementName null string
10 FallbackValue {{DependencyProperty.UnsetValue}} object {MS.Internal.NamedObject}
11 Flags PropDefault | ValidatesOnNotifyDataErrors System.Windows.Data.BindingBase.BindingFlags
12 IsAsync false bool
13 Mode Default System.Windows.Data.BindingMode
14 NotifyOnSourceUpdated false bool
15 NotifyOnTargetUpdated false bool
16 NotifyOnValidationError false bool
17 Path {System.Windows.PropertyPath} System.Windows.PropertyPath
18 RelativeSource null System.Windows.Data.RelativeSource
19 Source null object
20 SourceReference null MS.Internal.Data.ObjectRef
21 StringFormat null string
22 TargetNullValue {{DependencyProperty.UnsetValue}} object {MS.Internal.NamedObject}
23 TransfersDefaultValue true bool
24 TreeContextIsRequired false bool
25 UpdateSourceExceptionFilter null System.Windows.Data.UpdateSourceExceptionFilterCallback
26 UpdateSourceTrigger PropertyChanged System.Windows.Data.UpdateSourceTrigger
27 ValidatesOnDataErrors false bool
28 ValidatesOnExceptions false bool
29 ValidatesOnNotifyDataErrors true bool
30 ValidatesOnNotifyDataErrorsInternal true bool
31 ValidationRules Count = 0 System.Collections.ObjectModel.Collection<System.Windows.Controls.ValidationRule> {MS.Internal.Controls.ValidationRuleCollection}
32 ValidationRulesInternal Count = 0 System.Collections.ObjectModel.Collection<System.Windows.Controls.ValidationRule> {MS.Internal.Controls.ValidationRuleCollection}
33 XPath null string
34 _attachedPropertiesInPath 0 int
35 _bindsDirectlyToSource false bool
36 _doesNotTransferDefaultValue false bool
37 _flags PropDefault | ValidatesOnNotifyDataErrors System.Windows.Data.BindingBase.BindingFlags
38 _isAsync false bool
39 _isSealed true bool
40 _ppath {System.Windows.PropertyPath} System.Windows.PropertyPath
41 _source {MS.Internal.Data.ExplicitObjectRef} MS.Internal.Data.ObjectRef {MS.Internal.Data.ExplicitObjectRef}
42 _sourceInUse None System.Windows.Data.Binding.SourceProperties
43 _values {MS.Internal.UncommonValueTable} MS.Internal.UncommonValueTable
44 Static members
如何解决这个问题,这样我就不必在 WPF 中显式设置 "UpdateSourceTrigger=PropertyChanged"。
@更新 2017-06-03
我已将 link (click) 附加到示例项目以说明该问题。请用第 #35-#39 行打开 MainWindow.xaml 和 fiddle。 #36 行表示不工作行为,#39 行表示工作行为。
第 36 行
<local:RatingControl StarsCount="5" RatingValue="{Binding Rating, PresentationTraceSources.TraceLevel=High}" IsReadonly="False" HorizontalContentAlignment="Center" />
第 39 行
<local:RatingControl StarsCount="5" RatingValue="{Binding Rating, UpdateSourceTrigger=PropertyChanged, PresentationTraceSources.TraceLevel=High}" IsReadonly="False" HorizontalContentAlignment="Center" />
@Edit - 请求 XAML 代码
<UserControl x:Class="so_44248130.RatingControl"
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="24" d:DesignWidth="240">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<BitmapImage x:Key="StarEmpty" UriSource="pack://application:,,,/so_44248130;component/star_black_empty.png" CacheOption="OnLoad" CreateOptions="IgnoreImageCache" />
<BitmapImage x:Key="StarFull" UriSource="pack://application:,,,/so_44248130;component/star_black_full.png" />
</UserControl.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding StarsList, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Button Grid.Row="0" Grid.Column="0" Width="24" Height="24" MaxHeight="24" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Tag="{Binding}" Padding="0" HorizontalContentAlignment="Center" Click="ButtonBase_OnClick">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Grid.Column="0" Width="{Binding EmptyStarWidth}" Height="24" HorizontalAlignment="Left">
<Rectangle.Fill>
<ImageBrush ImageSource="{StaticResource StarEmpty}"
TileMode="Tile"
Stretch="Uniform"
AlignmentY="Top"
Viewport="0,0,24,3000"
ViewportUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
<Rectangle Grid.Row="0" Grid.Column="0" Width="{Binding FullStarWidth}" Height="24" HorizontalAlignment="Left">
<Rectangle.Fill>
<ImageBrush ImageSource="{StaticResource StarFull}"
TileMode="Tile"
Stretch="Uniform"
AlignmentY="Top"
Viewport="0,0,24,3000"
ViewportUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
</Grid>
</Button>
<Rectangle Grid.Row="0" Grid.Column="0" Height="24" Width="24" Visibility="{Binding IsReadonly, Converter={StaticResource BooleanToVisibilityConverter}}" Fill="#02FFFFFF" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
使用FrameworkPropertyMetadata
有什么具体原因吗?
如果您只是备份 属性 然后尝试使用 PropertyMetadata
.
参考here了解更多详情。
我已经弄明白了...部分...
在问题链接的示例项目中,应该导航到 RatingControl.xaml.cs
文件,行 #206-#228 (click)。这是 ButtonBase_OnClick
方法。在 if (star.Value ==
~ 部分下,我添加了绑定力 UpdateSource
。请参阅下面的代码。
if (star.Value == RatingValue)
{
RatingValue = 0;
}
else
{
RatingValue = star.Value;
}
BindingExpression binding = GetBindingExpression(RatingValueProperty);
if (binding != null)
{
binding.UpdateSource();
}
这会强制更新 BindingSource
并解决问题(这可能是某种解决方法.. 但也许它会让某人朝着正确的方向前进 post 真正有效的答案)。
注:
在调试时我检查了接收到的 BindingExpression
和名为 IsUpdateOnPropertyChanged
的 属性 由于某种原因被设置为 false
。我相信它应该设置为 true
但是我缺乏关于 WPF
内部的知识 post 它作为答案,因此 "note" 区域。