簡體   English   中英

如何在 WPF 中有條件地更改按鈕前景色?

[英]How to Change Button Foreground Color Conditionally in WPF?

我在ItemsControl (分頁類型控件)中有一個按鈕,我的視圖模型中有一個名為current_page的屬性。

我想將current_page值與 (1 / 2 / 3) 的Button Content進行比較,並想更改按鈕的前景色。

請看一下代碼。

我的視圖模型

public PaginationModel pagination
{
  get { return _pagination; }
  set { _pagination = value; OnPropertyChanged("pagination"); }
}

我的分頁模型

public class PaginationModel: INotifyPropertyChanged {
  private int _total_items;
  public int total_items {
    get {
      return _total_items;
    }
    set {
      _total_items = value;
      OnPropertyChanged("total_items");
    }
  }

  private int _items_per_page;
  public int items_per_page {
    get {
      return _items_per_page;
    }
    set {
      _items_per_page = value;
      OnPropertyChanged("items_per_page");
    }
  }

  private int _current_page;
  public int current_page {
    get {
      return _current_page;
    }
    set {
      if (value <= total_pages + 1 && value > 0) {
        _current_page = value;
        OnPropertyChanged("current_page");
      }
    }
  }

  private int _total_pages;
  public int total_pages {
    get {
      return _total_pages;
    }
    set {
      _total_pages = value;
      OnPropertyChanged("total_pages");
    }
  }

  private ObservableCollection < string > _PageList;

  public ObservableCollection < string > PageList {
    get {
      _PageList = new ObservableCollection < string > ();
      for (int i = 0; i < total_pages; i++) {
        _PageList.Add((i + 1).ToString());
      }
      return _PageList;
    }
    set {
      _PageList = value;
      OnPropertyChanged("PageList");
    }
  }
}

我的布局

<ItemsControl ItemsSource="{Binding pagination.PageList}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Margin="0">
                <Button Content="{Binding}"  CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
                                             Command="{Binding DataContext.ChangePage, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                                             Width="20"
                                             Margin="10,0"></Button>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

按鈕樣式模板

<Style TargetType="{x:Type Button}" >
    <Setter Property="Foreground" Value="{StaticResource WordOrangeBrush}"  />
    <Setter Property="Background" Value="Transparent"></Setter>
    <Setter Property="BorderThickness" Value="0"></Setter>
    <Setter Property="FontFamily" Value="{StaticResource HelveticaNeue}"></Setter>
    <Setter Property="FontSize" Value="14"></Setter>
    <Setter Property="Foreground" Value="#ff9f00"></Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}">
                    <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Transparent"></Setter>
            <Setter Property="Foreground" Value="#ff9f00" />
        </Trigger>
        <Trigger Property="IsMouseOver" Value="False">
            <Setter Property="Background" Value="Transparent"></Setter>
            <Setter Property="Foreground" Value="White" />
        </Trigger>
        <!--I want to bind current page value in place of 1-->
        <DataTrigger Binding="{Binding}" Value="1">
            <Setter Property="Foreground" Value="Red"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

價值轉換器解決方案

您不能將DataTriggerValue綁定到屬性,因為它不是依賴屬性。 您可以通過創建一個用於檢查頁面是否相等的自定義多值轉換器來解決此問題。

public class PageEqualityToBooleanConverter : IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
   {
      return (int)values[0] == System.Convert.ToInt32(values[1]);
   }

   public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
   {
      throw new InvalidOperationException();
   }
}

傳遞給轉換器的第一個值是作為int的當前頁面,第二個值是作為stringButton上的頁面。 您的current_pageint類型有點奇怪,但PageListstring類型的集合,這就是我們需要轉換第二個值的原因。

樣式之前在資源中創建轉換器的實例,以便您可以引用它。

<local:PageEqualityToBooleanConverter x:Key="PageEqualityToBooleanConverter"/>

最后,用下面的替換你的DataTrigger 我們正在使用MultiBinding來綁定多個值。 如果頁面值匹配,轉換器會將兩個值都轉換為True ,否則轉換為False

<DataTrigger Value="True">
   <DataTrigger.Binding>
      <MultiBinding Converter="{StaticResource PageEqualityToBooleanConverter}">
         <Binding Path="DataContext.pagination.current_page" RelativeSource="{RelativeSource AncestorType={x:Type ItemsControl}}"/>
         <Binding/>
      </MultiBinding>
   </DataTrigger.Binding>
   <Setter Property="Foreground" Value="Red"/>
</DataTrigger>

第一個綁定將找到父項ItemsControl以訪問包含current_page的視圖模型。 第二個綁定將綁定到關聯按鈕的數據上下文,即頁面字符串。 如果您將PageList項目類型更改為int這仍然有效。

建議

我想指出一些對您的代碼的觀察,可能會幫助您改進它。

  • 正如我已經提到的,您的集合項類型與您當前的項屬性類型不同似乎很奇怪。 如果您計划在其中包含除頁碼以外的其他屬性,請考慮將其int或創建單獨的頁面項視圖模型。
  • 您正在為Button定義隱式樣式,該樣式應用於范圍內的所有Button控件。 如果您僅在分頁控件中使用它,這可能沒問題,但如果您打算在其他地方使用它, DataTrigger應將DataTrigger包含在其中,因為它僅特定於此數據上下文。 在此基礎上創建單獨的樣式。 考慮@BionicCode 對此的評論。
  • 正如@Andy 在評論中指出的那樣, ListBox可能更適合分頁器,因為它具有SelectedItem的概念(以及可以綁定在DataTrigger項目容器上的IsSelected屬性),這就是您的想法試圖在這里手動完成。

DataTriggerValue屬性不能是數據綁定的。

你應該做的是創建一個代表一個類型Page ,一個加NumberIsCurrentPage屬性並更改類型PageList是一個ObservableCollection<Page>代替ObservableCollection<string>

然后,您可以簡單地查找相應的PagePageList並設置其IsCurrentPage每當從視圖模型屬性current_page屬性設置。

您還應該確保PageList屬性的 getter 不會在每次調用時創建新集合。

暫無
暫無

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

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