WPF附加属性触发两次
我正在努力学习依赖属性和附加属性,所以如果你发现我所做的没有用,请原谅我 我有一种常用的MVVM方法,其中的窗口的datacontext设置为VM,而View是一个datatemplate,其中包含一个针对此类VM的usercontrol 我试图使窗口容器尽可能的哑,因此我试图定义一些通常驻留在窗口XAML中的参数,例如使用附加属性通过usercontrol定义的高度 为此,我创建了以下类,在其中定义了附加属性:WPF附加属性触发两次,wpf,c#-4.0,attached-properties,Wpf,C# 4.0,Attached Properties,我正在努力学习依赖属性和附加属性,所以如果你发现我所做的没有用,请原谅我 我有一种常用的MVVM方法,其中的窗口的datacontext设置为VM,而View是一个datatemplate,其中包含一个针对此类VM的usercontrol 我试图使窗口容器尽可能的哑,因此我试图定义一些通常驻留在窗口XAML中的参数,例如使用附加属性通过usercontrol定义的高度 为此,我创建了以下类,在其中定义了附加属性: public static class WpfExtensions { p
public static class WpfExtensions
{
public static readonly DependencyProperty ContainerHeightProperty = DependencyProperty.RegisterAttached(
"ContainerHeight",
typeof(double),
typeof(WpfExtensions),
new FrameworkPropertyMetadata(300.0, FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure | FrameworkPropertyMetadataOptions.AffectsRender, ContainerHeight)
);
public static void SetContainerHeight(UIElement element, double value)
{
element.SetValue(ContainerHeightProperty, value);
}
public static double GetContainerHeight((UIElement element)
{
return (double)element.GetValue(ContainerHeightProperty);
}
private static void ContainerHeight(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is UserControl)
{
UserControl l_Control = (UserControl)d;
Binding l_Binding = new Binding();
l_Binding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1);
l_Binding.Path = new PropertyPath("Height");
l_Binding.Mode = BindingMode.OneWayToSource;
BindingOperations.SetBinding(d, e.Property, l_Binding);
}
}
}
如您所见,为了实现对容器窗口高度的控制,我在代码中创建了一个从attached属性到容器窗口的绑定
然而,集装箱的重量变化会被解雇两次。我第一次从默认值300更改为XAML中定义的1024。然后我立即收到另一个从1024回300,我不明白为什么
窗口代码非常简单:
<Window x:Class="WpfApplication.DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lcl="clr-namespace:WpfApplication"
Title="DialogWindow">
<Window.Resources>
<DataTemplate DataType="{x:Type lcl:Dialog_VM}">
<lcl:Dialog_VM_View />
</DataTemplate>
</Window.Resources>
<ContentPresenter Content="{Binding }" />
</Window>
最后是简单的视图模型
<UserControl x:Class="WpfApplication.Dialog_VM_View"
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:lcl="clr-namespace:WpfApplication"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
lcl:WpfExtensions.ContainerHeight="1024">
<StackPanel>
<TextBlock Text="This is a test" />
</StackPanel>
</UserControl>
您应该将父窗口的Height属性绑定到attached属性,而不是反过来绑定,不是吗
这将父窗口的高度绑定为1024,这是UserControl中dependency属性的值:
你的容器高度属性?WPFExtRead,我粘贴的第一段代码,使用USER控件,粘贴了第三段代码。而不是这种奇怪的方法,你是否考虑简单地设置窗口的siZoTeTimeFor属性?NOPE,而不是问题的范围。这正好达到了我所期望的。我尝试将目标绑定到源代码,并使用onewaytosource将目标作为控件,而正如您所示,将窗口作为目标,控件作为源代码进行绑定是正确的方法。我的大脑被视觉层次蒙蔽了。谢谢。@user1464603您还可能会发现绑定不再是必需的。只要ContentHeight以后不更改,就在Bind方法中将窗口的高度设置为当前ContentHeight属性值。对不起,stackoverflow新手。@Clemens。我知道这很有效。但是,如果我想在UserControl中保持逻辑的自包含性,包括进一步的绑定,例如从textbox.Text到同一UserControl中的attached属性以影响容器高度,那么使用direct值是没有帮助的。
private static void ContainerHeight(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is UserControl)
{
UserControl l_Control = (UserControl)d;
if (!l_Control.IsLoaded)
{
l_Control.Loaded += L_Control_Loaded;
}
else
{
Bind(l_Control);
}
}
}
private static void L_Control_Loaded(object sender, RoutedEventArgs e)
{
UserControl l_Control = (UserControl)sender;
Bind(l_Control);
}
private static void Bind(UserControl l_Control)
{
Window window = Window.GetWindow(l_Control);
Binding l_Binding = new Binding();
l_Binding.Path = new PropertyPath(WpfExtensions.ContainerHeightProperty);
l_Binding.Source = l_Control;
BindingOperations.SetBinding(window, Window.HeightProperty, l_Binding);
}