Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WPF附加属性触发两次_Wpf_C# 4.0_Attached Properties - Fatal编程技术网

WPF附加属性触发两次

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

我正在努力学习依赖属性和附加属性,所以如果你发现我所做的没有用,请原谅我

我有一种常用的MVVM方法,其中的窗口的datacontext设置为VM,而View是一个datatemplate,其中包含一个针对此类VM的usercontrol

我试图使窗口容器尽可能的哑,因此我试图定义一些通常驻留在窗口XAML中的参数,例如使用附加属性通过usercontrol定义的高度

为此,我创建了以下类,在其中定义了附加属性:

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);
}