2017-10-04 75 views
0

我努力學習依賴屬性和附加屬性,所以請原諒我,如果你發現什麼,我試圖做沒有用。WPF附加屬性觸發兩次

我有一個窗口,其DataContext設置到VM,並查看它是含有一個用戶控件靶向這一VM一個DataTemplate通常MVVM方法。

我想使窗口容器儘可能愚蠢,因此我試圖通過使用附加屬性通過usercontrol定義通常駐留在窗口XAML(例如高度)的一些參數。

爲了這個目的,我創建了下面的類,我定義的附加屬性:

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

你可以看到,實現了容器窗口的高度,我在代碼中創建從附加綁定的控制屬性直至容器窗口。

然而ContainerHeight變化會被解僱的兩倍。我第一次從300(默認)變爲1024(在XAML中定義的)。然後我立即收到從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> 
+0

哪裏是你的'ContainerHeight'房產嗎? – Bojje

+0

WpfExtensions,我粘貼的第一段代碼,與UserControl一起使用,我粘貼的第三段代碼。 – user1464603

+0

而不是這種奇怪的方法,你是否考慮簡單地設置窗口的SizeToContent屬性? – Clemens

回答

1

你應該父窗口的Height屬性綁定的附加屬性,而不是周圍的其他方法,不是嗎?

這套(綁定)的父窗口的Height1024這是依賴屬性在UserControl值:

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

這實現正是我所期待的。我複雜的事情想結合靶點的來源和使用onewaytosource與目標是控制,而你則顯示,與窗口作爲目標和控制是源是正確的方式結合。我達到了一個被視覺等級所遮蔽的大腦鎖定。謝謝。 – user1464603

+0

@ user1464603您可能還會發現綁定不再是必需的。只需在「綁定」方法中將窗口高度設置爲當前的ContentHeight屬性值(只要ContentHeight稍後不更改)。 – Clemens

+0

對不起,stackoverflow新秀。 – user1464603