Что мне нужно сделать, чтобы синтаксис элемента свойства работал для моего настраиваемого присоединенного свойства в Silverlight?

У меня есть такой класс:

public class Stretcher : Panel {

    public static readonly DependencyProperty StretchAmountProp = DependencyProperty.RegisterAttached("StretchAmount", typeof(double), typeof(Stretcher), null);

    public static void SetStretchAmount(DependencyObject obj, double amount)
    {
        FrameworkElement elem = obj as FrameworkElement;
        elem.Width *= amount;

        obj.SetValue(StretchAmountProp, amount);
    }
}

Я могу установить свойство stretch amount в XAML, используя синтаксис атрибута:

<UserControl x:Class="ManagedAttachedProps.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:map="clr-namespace:ManagedAttachedProps"
    Width="400" Height="300">

    <Rectangle Fill="Aqua" Width="100" Height="100" map:Stretch.StretchAmount="100" />

</UserControl>

и мой прямоугольник растянут, но я не могу использовать такой синтаксис элемента свойства:

<UserControl x:Class="ManagedAttachedProps.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:map="clr-namespace:ManagedAttachedProps"
    Width="400" Height="300">

    <Rectangle Fill="Aqua" Width="100" Height="100">
        <map:Stretcher.StretchAmount>100</map:Stretcher.StretchAmount>
    </Rectangle>
</UserControl>

с синтаксисом элемента свойства мой блок set, кажется, полностью игнорируется (я даже могу поместить туда недопустимые значения double), а метод SetStretchAmount никогда не вызывается.

Я знаю, что можно сделать что-то подобное, потому что VisualStateManager делает это. Я пробовал использовать типы, отличные от double, и, похоже, ничего не работает.


person Jacksonh    schedule 11.11.2008    source источник


Ответы (2)


Я думаю, что понял это, хотя я не совсем уверен, что понимаю причину, по которой это работает.

Чтобы ваш пример заработал, мне пришлось создать настраиваемый тип под названием Stretch со свойством под названием StretchAmount. Как только я это сделал и поместил в теги элементов свойств, все заработало. Иначе это не называлось.

public class Stretch
{
    public double StretchAmount { get; set; }
}

И свойство изменилось на ..

public static readonly DependencyProperty StretchAmountProp = DependencyProperty.RegisterAttached("StretchAmount", typeof(Stretch), typeof(Stretcher), null);

public static void SetStretchAmount(DependencyObject obj, Stretch amount) 
{ 
    FrameworkElement elem = obj as FrameworkElement; 
    elem.Width *= amount.StretchAmount; 
    obj.SetValue(StretchAmountProp, amount); 
}

Чтобы это работало в сценарии, в котором вы не используете элемент свойства, вам нужно будет создать преобразователь настраиваемого типа, чтобы это работало.

Надеюсь, это поможет, хотя и не объясняет, почему я все еще пытаюсь понять.

Кстати - для настоящей головоломки взгляните на VisualStateManager в отражателе. Свойство зависимости и метод установки для VisualStateGroups являются внутренними.

person Bryant    schedule 11.11.2008
comment
Очень интересно и несколько странно. Я попробую это завтра, когда у меня будет доступ к машине с Windows, и обязательно дам вам ответ, если он работает. Спасибо! - person Jacksonh; 12.11.2008

Итак, решение Брайанта работает, оно требует небольшой модификации XAML:

<Rectangle Fill="Aqua" Width="100" Height="100" x:Name="the_rect">
        <map:Stretcher.StretchAmount>
            <map:Stretch StretchAmount="100" />
        </map:Stretcher.StretchAmount>
</Rectangle>
person Jacksonh    schedule 12.11.2008