Как автоматически создать привязку внутри пользовательского элемента управления? - PullRequest
3 голосов
/ 13 января 2012

У меня есть пользовательский элемент управления панели инструментов с DependencyProperty IsBusy

Вот как я это использую:

<Controls:myToolbar 
                Grid.ColumnSpan="5" Mode="DataEntry" 
                Status="{Binding State, Converter={StaticResource ViewEditingStateToToolbarStateConverter}}"
                IsBusy="{Binding IsBusy}"/>

По соглашению все мои ВМ наследуются от базовой ВМ и имеют свойство IsBusy. Итак, я ЗНАЮ, что это свойство всегда будет доступно на ВМ.

Теперь у меня есть еще 4 свойства, как это. Вместо того, чтобы добавлять их в XAML для всех моих представлений, я хочу знать, как автоматически связать это IsBusy внутри кода элемента управления, чтобы мне не пришлось связываться в XAML?

EDIT

На самом деле я нашел ответ на свой вопрос: Silverlight: программно связывающие свойства элемента управления

Теперь мой вопрос:

Правильно ли применять эту привязку в конструкторе следующим образом?

public myToolbar()
        {
            this.DefaultStyleKey = typeof(myToolbar);

            var binding = new Binding("IsBusy") { Mode = BindingMode.TwoWay };
            this.SetBinding(IsBusyProperty, binding); 
        }

Должен ли я проверить, существует ли привязка XAML (другая привязка) к этому свойству, а не привязка? Это работает в любом случае, но мне интересно, если это плохо для производительности, запахов и т.д.?

Как насчет этого в onApplyTemplate. Это лучший способ?

if (GetBindingExpression(IsBusyProperty) == null)
            {
                var binding = new Binding("IsBusy") { Mode = BindingMode.TwoWay };
                this.SetBinding(IsBusyProperty, binding);
            }

1 Ответ

0 голосов
/ 14 января 2012

Было бы плохо, если бы вы попытались использовать этот элемент управления с моделью представления, у которой нет свойства IsBusy, но даже тогда вы получите только предупреждение об отладке в окне вывода, не о чем беспокоиться.

Что касается места привязки, конструктор подходит, если свойство зависимости, к которому вы привязываете, не выполняет никаких действий внутри своего обратного вызова.Но если свойство измененного обратного вызова пытается вызвать такие функции, как GetTemplateChild и извлечь внутренние элементы управления - тогда вам следует переместить привязку к функциям OnApplyTemplate, потому что только там вы можете быть уверены, что внутренние элементы управления существуют.

Кстати, если ваш proeprty для зависимостей не имеет обратного вызова с измененным свойством и используется только в шаблоне элемента управления, например {TemplateBinding IsBusy}, вы можете заменить эту строку на {Binding IsBusy}.Примерно так: с помощью привязки или триггеров данных:

<ControlTemplate TargetType="{x:Type Controls:myToolbar}">
    <Grid>
        <ContentControl x:Name="content" ... />
        <ProgressBar x:name="progress" ... />
    </Grid>
    <ControlTemplate.Triggers>
        <DataTrigger Binding="{Binding IsBusy}" Value="True">
            <Setter TargetName="progress" Property="Visibility" Value="Visible" />
        </DataTrigger>

Идея проста: TemplateBinding применяется к свойствам зависимостей элемента управления, тогда как Binding применяется к свойствам объекта DataContextили модель представления, и они могут сосуществовать без проблем.

...