WPF: Как реализовать универсальное свойство, доступное на всех элементах управления GUI? - PullRequest
0 голосов
/ 14 июня 2011

возможно ли реализовать свойство, которое может быть указано на каждом элементе управления GUI (т. Е. FrameworkElement)?То, что я представляю, это свойство типа Tag, однако я бы предпочел не использовать Tag, а мое собственное свойство.

РЕДАКТИРОВАТЬ: Из-за ответов Felice и CodeNaked я провел свои первые эксперименты со свойствами Attached Dependency Propertiesвторая попыткаНесмотря на то, что все проверяется дважды, установщик моего присоединенного свойства (SetAdsName()) никогда не будет вызываться, хотя регистрация присоединенного свойства прошла успешно без ошибок.Там нет сообщений об ошибках - как всегда с WPF.

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ads="clr-namespace:WAL.UI.Lib.Ads.Binding;assembly=WAL.UI.Lib"
        Title="Demo Page" Height="350" Width="525"
>
    <Grid>
        <Label ads:AdsNameRegistry.AdsName="SpecialLabelName" Content="Some Button Caption" />
    </Grid>
</Window>


public class AdsNameRegistry : DependencyObject
{
    public static readonly DependencyProperty AdsNameProperty = DependencyProperty.RegisterAttached( "AdsName", typeof(String), typeof(AdsNameRegistry), new FrameworkPropertyMetadata( "", FrameworkPropertyMetadataOptions.AffectsRender ) );

    public static void SetAdsName( UIElement element, String value )
    {
        try
        {
            MessageBox.Show( "SetAdsName(value=" + value + ")" );
            element.SetValue( AdsNameProperty, value );
        }
        catch (Exception ex)
        {
            Debug.Assert( false, "Exception in SetAdsName(): " + ex.Message + "\n\n" + ex );
            throw;
        }
    }

    public static String GetAdsName( UIElement element )
    {
        try
        {
            return (String) element.GetValue( AdsNameProperty );
        }
        catch (Exception ex)
        {
            Debug.Assert( false, "Exception in GetAdsName(): " + ex.Message + "\n\n" + ex );
            throw;
        }
    }
}

}

Я предположил, что SetAdsName () никогда не будет вызываться, потому что нет элемента как родителя внутрикодировка XAML.Но, похоже, это неверный вывод.

С уважением, Семь

Ответы [ 3 ]

3 голосов
/ 14 июня 2011

Прежде всего, да, вы хотите прикрепленное свойство.Но вы не реализуете шаблон правильно.

Никогда не помещайте никакую логику в ваши методы GetXxxx () или SetXxxx ().GetXxxx и SetXxxx должны содержать только вызовов GetValue и SetValue соответственно:

public static String GetAdsName(UIElement element)
{
    return (string) element.GetValue(AdsNameProperty);
}
public static void SetAdsName(UIElement element, String value)
{
    element.SetValue(AdsNameProperty, value);
}

Почему они не должны содержать никакой другой логики?Потому что при загрузке XAML ваш метод SetXxxx не будет вызываться.У команды WPF был выбор: они могли бы заставить загрузчик XAML использовать Reflection, чтобы найти ваш метод SetXxxx, и динамически вызывать его во время выполнения, чтобы ваш метод мог вызвать SetValue;или они могли бы удалить посредника и просто вызвать SetValue напрямую.Они выбрали последний вариант, потому что он намного проще и эффективнее.

Если вы хотите, чтобы побочные эффекты были установлены, когда вы задали свойство, вам нужно указать propertyChangedCallback при создании PropertyMetadata.В вашем случае:

public static readonly DependencyProperty AdsNameProperty =
    DependencyProperty.RegisterAttached("AdsName",
        typeof(String), typeof(AdsNameRegistry),
        new FrameworkPropertyMetadata("",
            FrameworkPropertyMetadataOptions.AffectsRender, OnAdsNameChanged));

private static void OnAdsNameChanged(DependencyObject sender,
    DependencyPropertyChangedEventArgs e)
{
    // do something with the new value
}
1 голос
/ 14 июня 2011

Это можно сделать с помощью Attached Property . Вы можете получить уведомление о присоединении свойства, зарегистрировавшись, как показано в следующем примере:

public static readonly DependencyProperty XYZProperty =
            DependencyProperty.RegisterAttached(
                "XYZ",
                typeof(object),
                typeof(TargetClass),
                new PropertyMetadata(OnXYZChanged)
                );

и реализация OnXYZChanged:

private static void OnXYZChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ...     
}

d будет объектом, к которому вы присоединяетесь, а в e.NewValue вы найдете новое значение свойства.

0 голосов
/ 14 июня 2011

Вы можете использовать прикрепленные свойства , чтобы добавить любое другое свойство, которое вы хотите. Примеры включают свойство Canvas.Left.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...