簡體   English   中英

如何使用多個依賴項屬性綁定到計算屬性

[英]How to bind to calculated property using multiple dependency properties

我正在嘗試構建一個WPF UserControl,我可以在整個項目中重用它。 它基本上是這樣的:

  • 水平線(稱為頂線)
  • 文本塊 - 水平線(底線)

當窗口調整大小並且太小時,我只顯示底線以節省空間。 所以我想有這些選擇:

  • 隱藏所有行
  • 僅顯示頂線
  • 只顯示底線

我正在使用三個依賴項屬性來間接設置每行的可見性:

  • 顯示行(啟用行)
  • 可以壓縮(根據可用空間顯示頂部或底部)
  • 顯示壓縮(顯示底線為true,顯示頂線為false)

直接綁定到依賴項屬性。 間接沒有。

現在的問題是我是否需要使用:

  1. FrameworkPropertyMetadata的FrameworkPropertyMetadataOptions.AffectsRender之類的標志
  2. 為DependencyProperty.Register創建FrameworkPropertyMetadata時的PropertyChangedCallback
  3. 值轉換器
  4. INotifyPropertyChanged的

我試過了什么

我嘗試了上面的所有四個選項,但我還不太了解它還能讓一個人工作。

我創建了從三個依賴項屬性返回計算值的常規屬性。 這些使用DependencyProperty.Register設置的默認值,它們不更新甚至不使用父用戶控件中設置的值。

當前狀態

<StackPanel>
    <Border Height="1"
            Background="Black"
            Margin="0 10 0 0"
            Visibility="{Binding ShowTopLine, ElementName=Root, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"/>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0"
                   Text="{Binding Text, ElementName=Root, Mode=TwoWay, FallbackValue=Heading}"
                   Margin="0 10 10 0" />
        <Border Grid.Column="1" 
                Height="1" 
                Margin="0 10 0 0" 
                Background="Black" 
                VerticalAlignment="Center" 
                Visibility="{Binding ShowBottomLine, ElementName=Root, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"/>
    </Grid>
</StackPanel>

代碼隱藏的相關部分,顯示三個依賴屬性之一:

internal partial class Heading
{
  public bool ShowBottomLine => ShowLine && (!CanCompress || ShowCompressed);

  public static readonly DependencyProperty CanCompressProperty = GetRegisterProperty("CanCompress", typeof(bool), true);

  public bool CanCompress
  {
    get => (bool) GetValue(CanCompressProperty);
    set => SetValue(CanCompressProperty, value);
  }

  // Same for other two properties

  public static DependencyProperty GetRegisterProperty(string name, Type type, object defaultValue)
  {
    return DependencyProperty.Register(name, type, typeof(Heading), new FrameworkPropertyMetadata(defaultValue));
  }
}

我如何在另一個用戶控件中使用標題:

<local:Heading Text="{Binding HeaderText}"
                                   CanCompress="False" 
                                   ShowLine="False"/>

我怎么能從這里開始? 我知道放棄計算的屬性會很簡單,但這意味着我需要在其他地方計算它們的狀態。 我想在標題中做到這一切。

主要問題似乎是計算出的屬性不會被強制刷新。 這是一個公平的總結嗎?

您可以通過定義ControlTemplate和簡單觸發器來實現此邏輯:

<UserControl x:Class="ExampleControl">
  <UserControl.Template>
    <ControlTemplate TargetType="ExampleControl">

      <StackPanel>
        <Border x:Name="TopLine"
                Background="Black" 
                Height="1"
                Margin="0 10 0 0" />
        <Grid>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text, FallbackValue=Heading}"
                     Margin="0 10 10 0" />
          <Border x:Name="BottomLine"
                  Grid.Column="1"
                  Height="1"
                  Margin="0 10 0 0"
                  Background="Black"
                  VerticalAlignment="Center" />
        </Grid>
      </StackPanel>

      <ControlTemplate.Triggers>
        <Trigger Property="ShowLines" Value="False">
          <Setter TargetName="TopLine" Property="Visibility" Value="Collapsed" />
          <Setter TargetName="BottomLine" Property="Visibility" Value="Collapsed" />
        </Trigger>

        <MultiTrigger>
          <MultiTrigger.Conditions>
            <Condition Property="CanCompress" Value="True" />
            <Condition Property="ShowCompressed" Value="True" />
          </MultiTrigger.Conditions>
          <Setter TargetName="TopLine"
                  Property="Visibility"
                  Value="Collapsed" />
        </MultiTrigger>

        <MultiTrigger>
          <MultiTrigger.Conditions>
            <Condition Property="CanCompress" Value="True" />
            <Condition Property="ShowCompressed" Value="False" />
          </MultiTrigger.Conditions>
          <Setter TargetName="BottomLine"
                  Property="Visibility"
                  Value="Collapsed" />
        </MultiTrigger>
      </ControlTemplate.Triggers>
    </ControlTemplate>
  </UserControl.Template>
</UserControl>

或者(並推薦)使用自定義控件( 擴展Control )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM