WPF передает ElementName в качестве параметра в стиль - PullRequest
0 голосов
/ 23 февраля 2020

У меня есть 3 TextBlocks, свойство видимости которых зависит от правила проверки 3 различных элементов (TextBoxes). Как я могу реорганизовать этот код так, чтобы ElementName абстрагировался, и у меня был только один определенный стиль вместо 3? Можно ли передать ElementName в качестве параметра в TextBlocks, к которым применяется этот стиль?

    <Style x:Key="textBlock_stockPriceWarning" TargetType="TextBlock">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=stockPriceTextBox}" Value="True">
                <Setter Property="Visibility" Value="Visible"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=stockPriceTextBox}" Value="False">
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="textBlock_taxRateWarning" TargetType="TextBlock">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=ordinaryTaxRateBox}" Value="True">
                <Setter Property="Visibility" Value="Visible"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=ordinaryTaxRateBox}" Value="False">
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="textBlock_capGainsTaxRateWarning" TargetType="TextBlock">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=capitalGainsTaxRateBox}" Value="True">
                <Setter Property="Visibility" Value="Visible"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), ElementName=capitalGainsTaxRateBox}" Value="False">
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

** Обновление: следуя совету Марка ниже, я попытался использовать следующий ControlTemplate и определение присоединенного свойства:

    <ControlTemplate x:Key="LabelWarning" TargetType="Label">
        <Border BorderBrush="AliceBlue"/>
        <ControlTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), 
                ElementName={Binding Path=(views:ElementNameHelper.ElementAlias), RelativeSource={RelativeSource Mode=TemplatedParent}}}" Value="True">
                <Setter Property="Visibility" Value="Visible"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=(Validation.HasError), 
                ElementName={Binding Path=(views:ElementNameHelper.ElementAlias), RelativeSource={RelativeSource Mode=TemplatedParent}}}" Value="False">
                <Setter Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

public static class ElementNameHelper
{
    public static readonly DependencyProperty ElementAliasProperty =
        DependencyProperty.RegisterAttached("ElementAlias",
            typeof(string), typeof(ElementNameHelper));

    public static string GetElementAlias(DependencyObject obj)
    {
        return obj.GetValue(ElementAliasProperty).ToString();
    }

    public static void SetElementAlias(DependencyObject target, string value)
    {
        target.SetValue(ElementAliasProperty, value);
    }
}

И вызывая его так:

        <Label Content="Stock price should be a positive number." 
               FontSize="12" HorizontalAlignment="Center"
               VerticalAlignment="Center" Foreground="Red"
                Margin="1" 
               views:ElementNameHelper.ElementAlias="stockPriceTextBox"
               Template="{StaticResource LabelWarning}"/>

Но тогда компилятор XAML говорит мне, что: «Binding» не может быть установлен в свойстве «ElementName» типа «Binding» , «Связывание» может быть установлено только для свойства DependencyObject объекта DependencyObject. Правильно ли я настроил эту настройку, и вы просто не можете использовать этот подход в ElementName? Или я что-то упустил с определением прикрепленного свойства?

1 Ответ

1 голос
/ 24 февраля 2020

Обычный способ сделать это с прикрепленным свойством .

Если вы просто хотите решение по дешевке и простоте, вы можете использовать Tag, который описан в документация как «произвольное значение объекта, которое может использоваться для хранения пользовательской информации». Прикрепленное свойство - лучший способ сделать это.

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