WPF:根据其值和视图模型属性

时间:2018-01-25 16:38:43

标签: wpf data-binding

好的,我在View Model

中有这个属性
public bool IsChecked
{
    get { return _isChecked; }
    set
    {
        _isChecked = value;
        OnPropertyChanged(); // I also try OnPropertyChanged("IsChecked");
    }
}

正如您可以看到此工具INotifyPropertyChanged

当这个property正在改变时,我可以看到它通知并获得正确的值。

这是我的Progress-Bar

<ProgressBar Name="progressBarColumn"
             Value="{Binding Progress, UpdateSourceTrigger=PropertyChanged}" 
             Width="{Binding Path=Width, ElementName=ProgressCell}" 
             Style="{StaticResource CustomProgressBar}" />

我的Progress-Bar style

<Style x:Key="CustomProgressBar" TargetType="ProgressBar">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ProgressBar" >
                <Grid x:Name="Root">
                    <Border Name="PART_Track" 
                            CornerRadius="0" 
                            Background="{DynamicResource ProgressBackgroundColor}"
                            BorderBrush="{DynamicResource ProgressBackgroundColor}"
                            BorderThickness="1" />
                    <Border Name="PART_Indicator" 
                            CornerRadius="0" 
                            Background="{DynamicResource ProgressBarFillColor}" 
                            BorderBrush="{DynamicResource ProgressBarFillColor}" 
                            BorderThickness="1" 
                            HorizontalAlignment="Left" />
                </Grid>
                <ControlTemplate.Triggers>

                    <DataTrigger Value="100" Binding="{Binding Path=Value, RelativeSource={RelativeSource AncestorType=ProgressBar}}">
                        <Setter Property="Background" Value="Green"/>
                    </DataTrigger>

                    <DataTrigger Value="False" Binding="{Binding IsChecked}">
                        <Setter Property="Background" Value="Red"/>
                    </DataTrigger>

                    <Trigger Property="Orientation" Value="Vertical">
                        <Setter TargetName="Root" Property="LayoutTransform">
                            <Setter.Value>
                                <RotateTransform Angle="270" />
                            </Setter.Value>
                        </Setter>
                        <Setter TargetName="Root" Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height}"/>
                        <Setter TargetName="Root" Property="Height" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"/>
                    </Trigger>

                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

所以这是目前无效的事情:

  1. 当我的Progress-Bar到达value的{​​{1}}我希望其100%颜色会发生变化,所以我添加了Background

    DataTrigger
  2. 因此,当<DataTrigger Value="100" Binding="{Binding Path=Value, RelativeSource={RelativeSource AncestorType=ProgressBar}}"> <Setter Property="Background" Value="Green"/> </DataTrigger> 达到Pregress-Bar时,这种效果根本不会影响100%

    我甚至也试过:

    <DataTrigger Value="100" Binding="{Binding Path=Value, RelativeSource={RelativeSource Self}}">
        <Setter Property="Background" Value="Red"/>
    </DataTrigger>
    
    1. 当我的View Model IsChecked property设置为false时,我希望我的Progress-Bar Background颜色会更改为Red } - 这也行不通。
    2. 我尝试搜索多个解决方案,但一次又一次地搜索相同结果 - 我的Progress-Bar``color根本没有变化。

      编辑:

      <Style x:Key="CustomProgressBar2" TargetType="ProgressBar">
          <Style.Triggers>
              <Trigger Value="100" Property="Value">
                  <Setter Property="Background" Value="{DynamicResource ProgressBarFillCompleteColor}"/>
                  <Setter Property="Foreground" Value="Transparent"/>
              </Trigger>
      
              <DataTrigger Value="False" Binding="{Binding IsChecked}">
                  <Setter Property="Background" Value="Red"/>
              </DataTrigger>
          </Style.Triggers>
          <Setter Property="Template">
              <Setter.Value>
                  <ControlTemplate TargetType="ProgressBar" >
                      <Grid x:Name="Root">
                          <Border Name="PART_Track" 
                                  CornerRadius="0" 
                                  Background="{DynamicResource ProgressBorderBrushColor}"
                                  BorderBrush="{DynamicResource ProgressBorderBrushColor}"
                                  BorderThickness="1" />
                          <Border Name="PART_Indicator" 
                                  CornerRadius="0" 
                                  Background="{TemplateBinding  Background}" 
                                  BorderBrush="{TemplateBinding  Background}" 
                                  BorderThickness="1" 
                                  HorizontalAlignment="Left" />
                      </Grid>
                  </ControlTemplate>
              </Setter.Value>
          </Setter>
      </Style>
      

1 个答案:

答案 0 :(得分:0)

首先,您需要正确实现INotifyPropertyChanged接口。

public event PropertyChangedEventHandler PropertyChanged;

private int _Progress;
private int _Progress;
public int Progress
{
    get {
        return _Progress;

    }
    set
    {
        _Progress = value;
        PropertyChanged(this, new PropertyChangedEventArgs("Progress"));
    }
}

然后改变你的风格。最好使用Style.Triggers

<Style.Triggers>
    <Trigger Value="100" Property="Value">
        <Setter Property="Background" Value="Green"/>
        <Setter Property="Foreground" Value="Pink"/>
    </Trigger>

    <DataTrigger Value="False" Binding="{Binding IsChecked}">
        <Setter Property="Background" Value="Red"/>
    </DataTrigger>
</Style.Triggers>

修改模板

内的barders上的背景绑定
<Border Name="PART_Track" 
    CornerRadius="0" 
    Background="{TemplateBinding Background}"
    BorderBrush="{TemplateBinding Background}"
    BorderThickness="1" />
<Border Name="PART_Indicator" 
    CornerRadius="0" 
    Background="{TemplateBinding Foreground}" 
    BorderBrush="{TemplateBinding Foreground}" 
    BorderThickness="1" 
    HorizontalAlignment="Left" />

当进度为100时更改背景就足够了,但当进度超过100时(如果需要),前景和背景将切换为默认值。如果您需要更改进度的颜色&gt; = 100,那么您需要使用ValueConverter而不是触发器。

编辑:

完整解决方案。

<Window x:Class="WpfApplication3.ProgressWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication3"
        mc:Ignorable="d"
        Title="ProgressWindow" Height="200" Width="400">
    <Window.Resources>
        <SolidColorBrush x:Key="ProgressBarFillCompleteColor" Color="Green"/>
        <SolidColorBrush x:Key="ProgressBorderBrushColor" Color="Gray"/>

        <Style x:Key="CustomProgressBar" TargetType="ProgressBar">
            <Setter Property="Foreground" Value="AliceBlue"/>
            <Setter Property="Background" Value="{DynamicResource ProgressBorderBrushColor}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ProgressBar" >
                        <Grid x:Name="Root">
                            <Border Name="PART_Track" 
                            CornerRadius="0" 
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding Background}"
                            BorderThickness="1" />
                            <Border Name="PART_Indicator" 
                            CornerRadius="0" 
                            Background="{TemplateBinding Foreground}" 
                            BorderBrush="{TemplateBinding Foreground}" 
                            BorderThickness="1" 
                            HorizontalAlignment="Left" />
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="Orientation" Value="Vertical">
                                <Setter TargetName="Root" Property="LayoutTransform">
                                    <Setter.Value>
                                        <RotateTransform Angle="270" />
                                    </Setter.Value>
                                </Setter>
                                <Setter TargetName="Root" Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Height}"/>
                                <Setter TargetName="Root" Property="Height" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <DataTrigger Value="False" Binding="{Binding IsChecked}">
                    <Setter Property="Background" Value="Red"/>
                </DataTrigger>
                <Trigger Value="100" Property="Value">
                    <Setter Property="Background" Value="Green"/>
                    <Setter Property="Foreground" Value="Transparent"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <DockPanel>
        <ProgressBar Name="progressBarColumn" DockPanel.Dock="Top" Height="20" Minimum="0" Maximum="100"
                        Value="{Binding Progress, UpdateSourceTrigger=PropertyChanged}" 
                        Style="{StaticResource CustomProgressBar}" />
        <StackPanel>
            <Button Content="Start" Click="Button_Click"/>
            <CheckBox Content="Check me" IsChecked="{Binding IsChecked}"/>
        </StackPanel>
    </DockPanel>
</Window>

查看和查看模型

using System;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace WpfApplication3
{
    /// <summary>
    /// Interaction logic for ProgressWindow.xaml
    /// </summary>
    public partial class ProgressWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public ProgressWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private int _Progress;
        public int Progress
        {
            get
            {
                return _Progress;

            }
            set
            {
                _Progress = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Progress"));
            }
        }

        private bool _IsChecked;
        public bool IsChecked
        {
            get
            {
                return _IsChecked;

            }
            set
            {
                _IsChecked = value;
                PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
            }
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            Progress = 0;
            await Task.Run(async () =>
            {
                var value = 0;
                while (value < 100)
                {
                    await Task.Delay(500);
                    await Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                        new Action(() =>
                        {
                            Progress += 10;
                        }));
                }
            }); 
        }
    }
}