В WPF есть ли способ привязать к свойствам братьев и сестер? - PullRequest
20 голосов
/ 16 мая 2009

У меня есть серия TextBlock и TextBox элементов управления. Есть ли способ применить Style к TextBlock с таким образом, чтобы они могли связываться с элементом управления сразу после них?

Я бы хотел иметь возможность сделать что-то вроде этого:

<Resources..>
    <Style x:Key="BindToFollowingTextBoxSibling">
        <Setter Property="TextBlock.Text" Value="{Binding RelativeSource={RelativeSource FollowingSibling}, Path=Text, Converter={StaticResource MyConverter}}" />
        <Setter Property="TextBlock.Background" Value="{Binding RelativeSource={RelativeSource FollowingSibling}, Path=Text, Converter={StaticResource TextToBrushConverter}}" />
        ... More properties and converters.
    </Style>
</Resources>

...

<TextBlock Style="{StaticResource BindToFollowingTextBoxSibling}"/>
<TextBox/>

<TextBlock Style="{StaticResource BindToFollowingTextBoxSibling}"/>
<TextBox/>
<TextBlock Style="{StaticResource BindToPreviousTextBoxSibling}"/>

Возможно ли что-то подобное?

Ответы [ 2 ]

24 голосов
/ 24 мая 2013

Я знаю, что это старая тема, но я нашел решение этой проблемы . Я был в состоянии использовать Предложение Аланд Ли, найденное здесь . Это не так универсально, как в CSS, но если вы знаете тип родительского элемента, это прекрасно работает даже в стиле .

Вот пример того, как я его использовал. У меня есть элемент управления TextBox, который подсвечивается «цветом подсветки», когда он имеет фокус. Кроме того, я хотел, чтобы связанный с ним элемент управления Label также загорался, когда TextBox имел фокус. Поэтому я написал Trigger для элемента управления Label, который включил его аналогично элементу управления TextBox. Этот триггер запускается пользовательским вложенным свойством IsFocusedByProxy. Затем мне нужно было привязать IsFocusedByProxy метки к IsFocused TextBox. Поэтому я использовал эту технику:

<Grid x:Name="MaxGrid">
    <Label  x:Name="MaxLabel"
            Content="Max:"  
            c5:TagHelper.IsFocusedByProxy="{Binding 
                                  Path=Children[1].IsFocused,
                                  RelativeSource={RelativeSource AncestorType=Grid}}" 
       />
     <c5:TextBoxC5Mediator x:Name="MaxTextBox"                          
                           DataContext="{Binding ConfigVm.Max_mediator}" />
</Grid>

В этот момент вы можете подумать, что это не лучше, чем просто использование ElementName в Binding. Но разница в том, что теперь я могу переместить эту привязку в стиль для повторного использования:

<Setter Property="C5_Behaviors:TagHelper.IsFocusedByProxy"
        Value="{Binding Path=Children[1].IsFocused,
                     RelativeSource={RelativeSource AncestorType=Grid}}" />

И теперь я могу, когда у меня есть View, полный этих вхождений, например так (я настроил необходимые стили, чтобы они применялись неявно, поэтому не отображается разметка, которая устанавливает стили):

<Grid x:Name="MaxGrid">
    <Label  x:Name="MaxLabel"
            Content="Max:"  />
    <c5:TextBoxC5Mediator x:Name="MaxTextBox"                          
                          DataContext="{Binding ConfigVm.Max_mediator}" />
 </Grid> 
 <Grid x:Name="MinGrid">
     <Label  x:Name="MinLabel"
             Content="Min:" />
     <c5:TextBoxC5Mediator x:Name="MinTextBox"                          
                           DataContext="{Binding ConfigVm.Min_mediator}" />
</Grid>
<Grid x:Name="StepFactorGrid">
    <Label  x:Name="StepFactorLabel"
            Content="Step Factor:" />
    <c5:TextBoxC5Mediator x:Name="StepFactorTextBox"                          
                          DataContext="{Binding ConfigVm.StepFactor_mediator}" />
</Grid>
<!-- ... and lots more ... -->

Что дает мне эти результаты :

Перед тем как у любого текстового поля есть фокус:

Before any TextBoxes have focus

С различными текстовыми полями, получающими фокус:

after focus 1

after focus 2

17 голосов
/ 16 мая 2009

Я думаю, что лучшее, что нужно сделать в этом случае, это связать с ElementName:

<TextBlock Text="{Binding ElementName=textBox1, Path=Text}" />
<TextBox x:Name="textBox1">this is the textBox's 1 text</TextBox>
<TextBlock Text="{Binding ElementName=textBox2, Path=Text}" />
<TextBox x:Name="textBox2">this is the textBox's 2 text</TextBox>

Будет достигнуто нечто подобное. Это работает для вас?

...