2017-10-04 5 views
0

依存プロパティと添付プロパティを学習しようとしていますので、何をしようとしているのかわからない場合は私を許してください。WPF添付プロパティ2回トリガ

私は、datacontextがVMに設定されたウィンドウと、そのVMをターゲットとするusercontrolを含むデータ型であるViewを持つ通常の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の変更は2回発生します。初めて300(デフォルト)から1024(XAMLで定義されているもの)に変更されました。それから私はすぐに1024から300に別の1を受け取り、私はなぜ理解していない。

ウィンドウのコードは非常に簡単です:

<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> 

、最終的には簡単なのViewModel

<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

は? – Bojje

+0

WpfExtensionsは、貼り付けたコードの最初の部分で、UserControlを使用して貼り付けたコードの3番目の部分です。 – user1464603

+0

この奇妙なアプローチの代わりに、単にWindowのSizeToContentプロパティを設定することを検討しましたか? – Clemens

答えて

1

あなたは他の方法で回避添付プロパティに親ウィンドウのHeightプロパティをバインドしてはなりません、あなたはすべきではありませんか?

このセット(バインド)UserControlで依存関係プロパティの値である1024に親ウィンドウのHeight

はあなた `ContainerHeight`財産である
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

関連する問題