C# 如何在WPF中有条件地更改按钮前景色?
我在ItemsControl分页种类控件中有一个按钮我在视图模型中有一个名为current_page的属性 我想将当前页面值与1/2/3的按钮内容进行比较,并想更改按钮的前景色 请看一下代码 我的视图模型C# 如何在WPF中有条件地更改按钮前景色?,c#,wpf,xaml,data-binding,C#,Wpf,Xaml,Data Binding,我在ItemsControl分页种类控件中有一个按钮我在视图模型中有一个名为current_page的属性 我想将当前页面值与1/2/3的按钮内容进行比较,并想更改按钮的前景色 请看一下代码 我的视图模型 public PaginationModel pagination { get { return _pagination; } set { _pagination = value; OnPropertyChanged("pagination"); } } 我的分页
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>
值转换器解决方案
无法将DataTrigger的值绑定到属性,因为它不是依赖项属性。您可以通过创建一个自定义多值转换器来解决这个问题,该转换器检查页面是否相等
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值,第二个值是按钮上的页面的string值。有点奇怪,您当前的_页面是int类型,但是PageList是string类型的集合,这就是为什么我们需要转换第二个值的原因
在创建样式之前,在资源中创建转换器的实例,以便可以引用它
<local:PageEqualityToBooleanConverter x:Key="PageEqualityToBooleanConverter"/>
第一个绑定将找到父项控件以访问包含当前页面的视图模型。第二个绑定将绑定到相关按钮的数据上下文,即页面字符串。如果将PageList项类型更改为int,此选项仍然有效
建议
我想指出一些对代码的观察,这些观察可能会帮助您改进代码
正如我已经提到的,集合项类型与当前项属性类型不同似乎很奇怪。如果计划拥有比页中的页码更多的属性,请考虑使其为int或创建单独的页项视图模型。
您正在为按钮定义隐式样式,该样式将应用于范围中的所有按钮控件。如果您仅在分页控件中使用它,这可能没问题,但如果您打算在其他位置使用它,则不应将DataTrigger包含在其中,因为它仅特定于此数据上下文。基于此样式创建单独的样式。考虑一下BioNICCODE对此的评论。
正如@Andy在评论中指出的,a可能更适合paginator,因为它的项容器上有SelectedItem和IsSelected属性的概念,可以绑定到DataTrigger中,这就是您在这里尝试手动执行的操作。
值转换器解决方案
无法将DataTrigger的值绑定到属性,因为它不是依赖项属性。您可以通过创建一个自定义多值转换器来解决这个问题,该转换器检查页面是否相等
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值,第二个值是按钮上的页面的string值。有点奇怪,您当前的_页面是int类型,但是PageList是string类型的集合,这就是为什么我们需要转换第二个值的原因
在创建样式之前,在资源中创建转换器的实例,以便可以引用它
<local:PageEqualityToBooleanConverter x:Key="PageEqualityToBooleanConverter"/>
第一个绑定将找到父项控件以访问包含当前页面的视图模型。第二个绑定将绑定到相关按钮的数据上下文,即页面字符串。如果将PageList项类型更改为int,此选项仍然有效
建议
我想指出一些对代码的观察,这些观察可能会帮助您改进代码
正如我已经提到的,集合项类型与当前项属性类型不同似乎很奇怪。如果计划拥有比页中的页码更多的属性,请考虑使其为int或创建单独的页项视图模型。
您正在为按钮定义隐式样式,该样式将应用于范围中的所有按钮控件。如果您仅在分页控件中使用它,这可能没问题,但如果您打算在其他位置使用它,则不应将DataTrigger包含在其中,因为它仅特定于此数据上下文。基于此样式创建单独的样式。考虑一下BioNICCODE对此的评论。
正如@Andy在评论中指出的,a可能更适合paginator,因为它的项容器上有SelectedItem和IsSelected属性的概念,可以绑定到DataTrigger中,这就是您在这里尝试手动执行的操作。
DataTrigger的Value属性不能是数据绑定的
您应该做的是创建一个表示页面的类型,向其添加一个数字和IsCurrentPage属性,并将PageList的类型更改为ObservableCollection而不是ObservableCollection
然后,只要在页面列表中查找相应的页面,并在设置当前页面属性时从视图模型中设置其IsCurrentPage属性即可
您还应该确保PageList属性的getter不会在每次调用时创建新集合。DataTrigger的Value属性不能进行数据绑定
您应该做的是创建一个表示页面的类型,添加一个数字,然后IsCurrentP
属性,并将页列表的类型更改为ObservableCollection,而不是ObservableCollection
然后,只要在页面列表中查找相应的页面,并在设置当前页面属性时从视图模型中设置其IsCurrentPage属性即可
您还应该确保PageList属性的getter不会在每次调用时创建一个新集合。由于触发器不能触发按钮的属性,因此DataTrigger不应该是按钮的ControlTemplate的一部分,它是一个内部控件上下文,独立于任何数据类型。由于触发器在当前按钮的DataContext的属性上触发,因此DataTrigger必须位于按钮外部,它可以像在样式目标按钮中一样访问DataContext,或者在项目模板的DataTemplate中更好地访问DataContext。在这里,您所处的上下文专门针对特定的DataContext,即数据类型。您可以将其作为listbox而不是itemscontrol绑定到selecteditem的属性。使PageList成为viewmodels的列表,而不仅仅是字符串。将笔刷属性添加到该属性。或者使用转换器将数字转换为画笔。具有WordOrangeBush的fallbackvalue。由于触发器在触发按钮的属性时不起作用,因此DataTrigger不应是按钮的ControlTemplate的一部分,它是一个内部控件上下文,独立于任何数据类型。由于触发器在当前按钮的DataContext的属性上触发,因此DataTrigger必须位于按钮外部,它可以像在样式目标按钮中一样访问DataContext,或者在项目模板的DataTemplate中更好地访问DataContext。在这里,您所处的上下文专门针对特定的DataContext,即数据类型。您可以将其作为listbox而不是itemscontrol绑定到selecteditem的属性。使PageList成为viewmodels的列表,而不仅仅是字符串。将笔刷属性添加到该属性。或者使用转换器将数字转换为画笔。具有WordOrangeBush的后备值。