我在ItemsControl
(分页类型控件(中有一个按钮,在我的视图模型中我有一个名为current_page
的属性。
我想将current_page
的值与Button
的Content
进行比较,即(1/2/3(,并想更改按钮的前景色。
请看一下代码。
我的ViewModel
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
的Value
绑定到属性,因为它不是依赖属性。您可以通过创建一个自定义的多值转换器来检查页面是否相等来解决此问题。
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
的当前页面,第二个值是Button
上作为string
的页面。有点奇怪的是,您的current_page
是int
类型,但PageList
是string
类型的集合,这就是为什么我们需要转换第二个值。
在您的风格之前,在您的资源中创建转换器的实例,以便您可以引用它。
<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
不应包含在其中,因为它仅特定于此数据上下文。在此基础上创建单独的样式。考虑一下@BionicCode对此的评论 - 正如@Andy在评论中指出的那样,
ListBox
可能更适合分页器,因为它有SelectedItem
的概念(以及可以绑定到DataTrigger
中的项目容器上的IsSelected
属性(,这正是您在这里手动尝试做的
DataTrigger
的Value
属性不能进行数据绑定。
您应该创建一个代表Page
的类型,向其添加Number
和IsCurrentPage
属性,并将PageList
的类型更改为ObservableCollection<Page>
而不是ObservableCollection<string>
。
然后,只要设置了current_page
属性,就可以在PageList
中查找相应的Page
,并从视图模型中设置其IsCurrentPage
属性。
您还应该确保PageList
属性的getter不会在每次调用时创建新的集合。