2

私は何か簡単なことをしようとしています-DependencyPropertyを作成してからそれにバインドします。ただし、アプリを起動してもゲッターが起動しないようです。(解決策は私が頭を叩いて「Doh!」に行くようになると思いますが、それでも。:))

何か案は?

コードビハインドコード:

public static readonly DependencyProperty PriorityProperty = 
        DependencyProperty.Register("Priority", 
        typeof (Priority), typeof (PriorityControl), null);

public Priority Priority
{
    get { return (Priority)GetValue(PriorityProperty); }
    set { SetValue(PriorityProperty, value); }
}

XAMLの制御:

<ListBox Background="Transparent" 
         BorderThickness="0" 
         ItemsSource="{Binding Path=Priorities}" 
         Name="PriorityList" 
         SelectedItem="{Binding Path=Priority, Mode=TwoWay}">
  <ListBox.ItemTemplate>
    <DataTemplate>
        <Grid Height="16" Width="16">
          <Border BorderBrush="Black"
                  BorderThickness="2"
                  CornerRadius="3"
                  Visibility="{Binding RelativeSource=
                       {RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected, Converter={StaticResource boolToVisibilityConverter}}" />
          <Border CornerRadius="3" Height="12" Width="12">
            <Border.Background>
              <SolidColorBrush Color="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=Content, Converter={StaticResource priorityToColorConverter}}" />
            </Border.Background>
          </Border>
        </Grid>
    </DataTemplate>
   </ListBox.ItemTemplate>
   <ListBox.ItemsPanel>
     <ItemsPanelTemplate>
       <StackPanel Orientation="Horizontal"/>
     </ItemsPanelTemplate>
   </ListBox.ItemsPanel>
 </ListBox>

バインディングステートメント:

<UI:PriorityControl Grid.Column="8" 
                    Priority="{Binding Path=Priority}" 
                    VerticalAlignment="Center"/>

その他の注意事項:

  • バインディングはUserControlにあります
  • UserControlにはPriorityControlが含まれています
  • PriorityControlにはDependencyPropertyが含まれています
  • UserControlが適切なデータを取得しているデータを確認しました。他のすべてのバインディングが機能します。
  • マウスを使用してPriorityControlの選択を変更すると、すべてが適切に起動します。動作していないのは、値の初期設定だけです。
  • 優先度は列挙型です。

編集:私はさらに2つのことを試しました。最初に、値へのバインディングを双方向にしましたが、それは機能しませんでした。次に、プロパティ変更コールバックを依存関係プロパティに追加し、次のようにOnPropertyChangedを呼び出すようにしました。

public static readonly DependencyProperty PriorityProperty =
        DependencyProperty.Register("Priority", typeof (Priority), typeof (PriorityControl), new PropertyMetadata(HandleValueChanged));

private static void HandleValueChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
   var npc = dependencyObject as PriorityControl;
   npc.OnPropertyChanged("Priority");
}

それもうまくいきませんでした。コントロールのApplyTemplateをオーバーライドしてプロパティ変更通知を強制しようとしましたが、初期ロード時に値が設定されません。値を変更して、すべてが正常に起動することを確認できますが、何も発生しないのは初めてです。

4

3 に答える 3

1

DependencyProperty の getter と setter は、あなた以外には呼び出されません

これらは、(多くのキャストと GetValue/SetValue への呼び出しを節約するために) 利益のために生成された単純なヘルパーです。

DP でのすべての作業 (アニメーション、バインディングなど) は、SetValue と GetValue の呼び出しを介して直接行われます。

値の変更をキャッチする必要がある場合は、Register 呼び出しで変更コールバックを提供します。

注: 添付プロパティ (つまりRegisterAttachedの代わりに使用) は、実際にはXAML の解析中Registerにセッターを使用しますが、通常の DP では使用されないため、これは別の話です。

アップデート:

Register にデフォルト値を設定していないため、デフォルトで 0 になります (これは列挙値「Normal」です)。それをバインディングの最初の値として設定すると、変更がないため、トリガーされません。

1 つの解決策:最初の 0 値として「none」列挙型を追加して、「Normal」(値 1) が変更を引き起こすようにします。または、Register に「Normal」以外のデフォルト値を設定します。

于 2012-06-07T11:18:34.920 に答える
1

プロパティの定義中に値が既に設定されている場合、依存関係プロパティを実行すると、正しく動作しないことに気付きました。アプリケーション内で値を設定する際に問題がなかったとのことでしたので、配管の問題はないと仮定します。

以下の例を考えてみましょう。

XAML

<UI:PriorityControl Priority="{Binding Path=Priority, Mode=TwoWay}"/>

コード

public enum Priority
{
    Normal,
    Low,
    High
}

public class PriorityControl : UserControl
{    
    public static readonly DependencyProperty PriorityProperty =
      DependencyProperty.Register("Priority", typeof(Priority), typeof(PriorityControl), new PropertyMetadata(DependencyProperty.UnsetValue, OnPriorityPropertyChanged);

    public Priority Priority
    {
        get { return (Priority)this.GetValue(PriorityProperty); }
        set { this.SetValue(PriorityProperty, value); }
    }

    private static void OnPriorityPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        PriorityControl control = sender as PriorityControl;
        if (control != null)
        {
            // Do what you wanted to here.
        }
    }
}

列挙型を使用していて、既定値を指定していない場合 (作成時に依存関係プロパティに PropertyMetadata オブジェクトを提供していないように見える)、既定値は列挙型の既定値になります。上記の例では、「通常」になります。コントロールの作成時に値を Normal に設定しようとすると、値が既にその値と等しいため、コールバックは呼び出されません。

これを正しく機能させるには、プロパティを定義したときに行ったように、DependencyProperty.UnsetValue を PropertyMetadata オブジェクトに渡す必要があります。これにより、値が最初に設定されるときに OnPriorityPropertyChanged メソッドを呼び出すことができます。

それがそれを修正するのに役立つことを願っています!

于 2012-06-07T19:14:13.390 に答える
0

100%確実ではありませんが、Priority バインディングを TwoWay に変更するのと同じくらい簡単かもしれません。

<UI:PriorityControl Grid.Column="8" 
                    Priority="{Binding Path=Priority, Mode=TwoWay}" 
                    VerticalAlignment="Center"/>
于 2012-06-07T09:39:30.183 に答える