StaticResource、文字渐变、Canvas进度条、转换器、右键菜单、触发器、验证模板等

21-StaticResource的使用

StaticResource也是个扩展标记,而它呢就起到一个引入的作用,引入数据字典中定义的一个静态资源

比如下面

<Window x:Class="WpfApplication2.MainWindow"
        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:WpfApplication2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style x:Key="myButton" TargetType="Button">
            <Setter Property="Width" Value="200"/>
            <Setter Property="Height" Value="40"/>
            <Setter Property="Margin" Value="10"/>
            <Setter Property="Background" Value="Orange"/>
        </Style>
    </Window.Resources>
    <StackPanel Orientation="Vertical">
        <Button Style="{StaticResource myButton}">点击</Button>
        <Button>点击2</Button>
        <Button Style="{StaticResource myButton}">点击3</Button>
        <Button>点击3</Button>
    </StackPanel>
</Window>Code language: HTML, XML (xml)

22-文字颜色渐变效果

<Style x:Key="textBlockStyle" TargetType="TextBlock">
            <!--字体渐变-->
            <Setter Property="Foreground">
                <Setter.Value>
                    <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
                        <GradientStop Color="Red" Offset="0.0" />
                        <GradientStop Color="Blue" Offset="0.5" />
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="FontSize" Value="200"/>
            <Setter Property="Opacity" Value="0.02"/>
        </Style>Code language: HTML, XML (xml)

增加一个样式

在相应的地方 使用

<TextBlock Style="{StaticResource textBlockStyle}">Code language: HTML, XML (xml)

23-使用Canvas模拟实现进度条

由于windows7下面的进度条感觉不好看 没有扁平化效果 所以使用Canvas来实现

<Canvas Grid.Row="0" Grid.Column="0" Background="White" Height="{Binding Index[0].Height}" VerticalAlignment="Bottom"/>
        <Canvas Grid.Row="0" Grid.Column="0" Background="{Binding Index[0].Color}" VerticalAlignment="Bottom">
            <Canvas.Height>
                <MultiBinding Converter="{StaticResource cvtDate}">
                    <Binding Path="Index[0].Max"/>
                    <Binding Path="Index[0].Count"/>
                    <Binding Path="Index[0].Height"/>
                </MultiBinding>
            </Canvas.Height>
        </Canvas>Code language: HTML, XML (xml)
xmlns:local="clr-namespace:WpfApp2"
             mc:Ignorable="d" 
             BorderBrush="Transparent"
             BorderThickness="0"
             d:DesignHeight="450" d:DesignWidth="800" MinWidth="45" Margin="2.5,0,2.5,0">
    <UserControl.Resources>
        <Style TargetType="ProgressBar">
            <Setter Property="Background" Value="#ccc"></Setter>
            <Setter Property="Foreground" Value="#638A2D"></Setter>
            <Setter Property="FontSize" Value="12"></Setter>
        </Style>

        <local:MathConverter x:Key="cvtDate"/>Code language: JavaScript (javascript)
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;

namespace WpfApp2
{
    public class MathConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            double max = System.Convert.ToDouble(values[0]);
            double count = System.Convert.ToDouble(values[1]);
            double height = System.Convert.ToDouble(values[2]);
            return height*count/max;
        }

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

下面是我们的例子

<Window x:Class="PrograssDemo.MainWindow"
        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:PrograssDemo"
        mc:Ignorable="d"
        Background="Blue"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:MathConverter x:Key="cvtDate"/>
    </Window.Resources>
    <StackPanel>
        <ProgressBar Maximum="{Binding Max}" Minimum="0" Value="{Binding Value}" Height="20" Width="{Binding Width}" Margin="50" HorizontalAlignment="Left"></ProgressBar>

        <Grid>
            <Canvas Width="{Binding Width}" Height="20" Background="White" Margin="50" HorizontalAlignment="Left"></Canvas>
            <Canvas Height="20" Background="Green" Margin="50" HorizontalAlignment="Left">
                <Canvas.Width>
                    <MultiBinding Converter="{StaticResource cvtDate}">
                        <Binding Path="Max"/>
                        <Binding Path="Value"/>
                        <Binding Path="Width"/>
                    </MultiBinding>
                </Canvas.Width>
            </Canvas>
        </Grid>
    </StackPanel>
</Window>Code language: HTML, XML (xml)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace PrograssDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private ProgressViewModel progressViewModel = new ProgressViewModel() { Value = 20,Max = 100,Width = 500 };
        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = progressViewModel;

            new Thread(new ThreadStart(Deal)) { IsBackground = true }.Start();
        }

        private void Deal()
        {
            while (true)
            {
                progressViewModel.Value++;
                if(progressViewModel.Value > progressViewModel.Max)
                {
                    progressViewModel.Value = 0;
                }
                Thread.Sleep(200);
            }
        }
    }
}Code language: HTML, XML (xml)
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace PrograssDemo
{
    public class MathConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            double max = System.Convert.ToDouble(values[0]);
            double value = System.Convert.ToDouble(values[1]);
            double width = System.Convert.ToDouble(values[2]);
            return width * value / max;//500 * 5 / 100
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PrograssDemo
{
    public class ProgressViewModel: INotifyPropertyChanged
    {
        private int _value;

        public int Value
        {
            get
            {
                return _value;
            }

            set
            {
                _value = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value"));
            }
        }

        private int _width;

        public int Width
        {
            get
            {
                return _width;
            }

            set
            {
                _width = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Width"));
            }
        }

        private int _max;

        public int Max
        {
            get
            {
                return _max;
            }

            set
            {
                _max = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Max"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}Code language: PHP (php)

24-IMultiValueConverter

可以在XAML中传入多个绑定的值。然后在后台代码中(实现了IMultiValueConverter的转换器),然后进行转换

25-IValueConverter

它和IMultiValueConverter一样的作用 区别就是IMultiValueConverter 这个是可以传入多个绑定的值 而IValueConverter 就只能一个

private int _week;

        public int Week
        {
            get
            {
                return _week;
            }

            set
            {
                _week = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Week"));
            }
        }Code language: JavaScript (javascript)
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace PrograssDemo
{
    public class WeekConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int week = System.Convert.ToInt32(value);
            switch (week)
            {
                case 0:return "星期天";
                case 1:return "星期一";
                case 2:return "星期2";
                case 3:return "星期3";
                case 4:return "星期si";
                case 5:return "星期五";
                case 6:return "星期六";
                default: return "不值钱";
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
<Window x:Class="PrograssDemo.MainWindow"
        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:PrograssDemo"
        mc:Ignorable="d"
        Background="Blue"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:MathConverter x:Key="cvtDate"/>
        <local:WeekConverter x:Key="weekConvert"/>
    </Window.Resources>
    <StackPanel>
        <ProgressBar Maximum="{Binding Max}" Minimum="0" Value="{Binding Value}" Height="20" Width="{Binding Width}" Margin="50" HorizontalAlignment="Left"></ProgressBar>

        <Grid>
            <Canvas Width="{Binding Width}" Height="20" Background="White" Margin="50" HorizontalAlignment="Left"></Canvas>
            <Canvas Height="20" Background="Green" Margin="50" HorizontalAlignment="Left">
                <Canvas.Width>
                    <MultiBinding Converter="{StaticResource cvtDate}">
                        <Binding Path="Max"/>
                        <Binding Path="Value"/>
                        <Binding Path="Width"/>
                    </MultiBinding>
                </Canvas.Width>
            </Canvas>
        </Grid>

        <TextBlock Text="{Binding Week,Converter={StaticResource weekConvert},ConverterParameter='星期几'}"></TextBlock>
    </StackPanel>
</Window>Code language: HTML, XML (xml)

26-右键菜单ContextMenu

WPF中的右键菜单主要是通过ContextMenu来实现,ContextMenu的使用有两种方式

一、在Resources中声明,在控件中使用。

1.在Resources中添加ContextMenu

<Window.Resources>
        <ContextMenu x:Key="ContextMenu">
            <MenuItem Name="MiFullScreen" Header="全屏"/>
            <Separator></Separator>
            <MenuItem Name="MiPlay" Header="播放"/>
        </ContextMenu>
    </Window.Resources>Code language: HTML, XML (xml)

2.在控件中使用ContextMenu

直接在控件的ContextMenu属性中关联即可。

<GroupBox ContextMenu="{StaticResource ContextMenu}">
            
        </GroupBox>Code language: HTML, XML (xml)

3.为每个MenuItem写Click事件

此方法的优点在于只声明一次,可以在多个控件中同时使用

二、在控件中直接声明

<GroupBox >
            <GroupBox.ContextMenu>
                <ContextMenu>
                    <MenuItem Name="MenuItem1" Header="文件"/>
                    <MenuItem Name="MenuItem2" Header="编辑"/>
                </ContextMenu>
            </GroupBox.ContextMenu>
        </GroupBox>Code language: HTML, XML (xml)
<Window x:Class="PrograssDemo.MainWindow"
        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:PrograssDemo"
        mc:Ignorable="d"
        Background="Blue"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:MathConverter x:Key="cvtDate"/>
        <local:WeekConverter x:Key="weekConvert"/>
        <ContextMenu x:Key="ContextMenu">
            <MenuItem Name="MiFullScreen" Header="全屏"/>
            <Separator></Separator>
            <MenuItem Name="MiPlay" Header="播放"/>
        </ContextMenu>
    </Window.Resources>
    <StackPanel ContextMenu="{StaticResource ContextMenu}">
        <ProgressBar Maximum="{Binding Max}" Minimum="0" Value="{Binding Value}" Height="20" Width="{Binding Width}" Margin="50" HorizontalAlignment="Left"></ProgressBar>

        <Grid>
            <Canvas Width="{Binding Width}" Height="20" Background="White" Margin="50" HorizontalAlignment="Left"></Canvas>
            <Canvas Height="20" Background="Green" Margin="50" HorizontalAlignment="Left">
                <Canvas.Width>
                    <MultiBinding Converter="{StaticResource cvtDate}">
                        <Binding Path="Max"/>
                        <Binding Path="Value"/>
                        <Binding Path="Width"/>
                    </MultiBinding>
                </Canvas.Width>
            </Canvas>
        </Grid>

        <TextBlock Text="{Binding Week,Converter={StaticResource weekConvert},ConverterParameter='星期几'}"></TextBlock>
    </StackPanel>
</Window>Code language: HTML, XML (xml)

27-属性触发器-PropertyTrigger

触发器有三种类型:

  • 属性触发器Property Trigger:当Dependency Property的值发生改变时触发。
  • 数据触发器Data Trigger: 当普通.NET属性的值发生改变时触发。
  • 事件触发器Event Trigger: 当路由时间被触发时调用。

触发器,从某种意义上来说它也是一种Style,因为它包含有一个Setter集合,并根据一个或多个条件执行Setter中的属性改变。属性触发器是在当某个依赖属性的值发生变化时触发执行一个Setter的集合,当属性失去这个值时,这些被触发执行的Setter集合会自动被撤销。

<Window x:Class="WpfApp4.MainWindow"
        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:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style x:Key="buttonMouseOver" TargetType="{x:Type Button}">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="RenderTransform">
                        <Setter.Value>
                            <RotateTransform Angle="10"></RotateTransform>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
                    <Setter Property="Background" Value="Green" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel VerticalAlignment="Center">
        <Button Width="200" Style="{StaticResource buttonMouseOver}">按钮</Button>       
    </StackPanel>
</Window>Code language: HTML, XML (xml)

此外 还可以用来进行验证。比如输入错误的时候 改变文本框的外观。

<Window x:Class="TriggerDemo.MainWindow"
        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:TriggerDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style x:Key="myBtn" TargetType="Button">
            <Setter Property="Width" Value="250"/>
            <Setter Property="Height" Value="30"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Width" Value="250"/>
                    <Setter Property="Height" Value="60"/>
                    <Setter Property="RenderTransform">
                        <Setter.Value>
                            <RotateTransform Angle="90"></RotateTransform>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
        <Button Style="{StaticResource myBtn}">点我</Button>
    </StackPanel>
</Window>Code language: HTML, XML (xml)

28-属性触发器应用-错误提示引用

我们可以在一些表单控件 比如textbox等 做一些验证 如果输入不对 则让文本框边框或者其他属性 做一些修改。这样子 达到提示效果。比如 我们要输入一个网址 我们可以添加一个网址的验证类 然后这个类去进行验证 判断用户填写的是不是网址。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApp4
{
    public class MyViewModel:INotifyPropertyChanged
    {
        private string _webSite;

        public string WebSite
        {
            get
            {
                return _webSite;
            }

            set
            {
                _webSite = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("WebSite"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}Code language: PHP (php)
<Window x:Class="WpfApp4.MainWindow"
        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:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style x:Key="validateTextBoxStyle" TargetType="{x:Type TextBox}">
            <Setter Property="Width" Value="300" />
            <Setter Property="Height" Value="30" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="BorderBrush" Value="Red"/>
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel VerticalAlignment="Center">
        <TextBox Style="{StaticResource validateTextBoxStyle}">
            <TextBox.Text>
                <Binding UpdateSourceTrigger="PropertyChanged" Path="WebSite">
                    <Binding.ValidationRules>
                        <local:HttpValidationRule/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>

        </TextBox>
        <TextBox Width="300" Height="30" Margin="5"></TextBox>
    </StackPanel>
</Window>Code language: HTML, XML (xml)
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace WpfApp4
{
    public class HttpValidationRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            string url = value.ToString();
            if (!url.EndsWith("http://", StringComparison.InvariantCultureIgnoreCase))
            {
                return new ValidationResult(false,url+ "不是一个无效的网址");
            }
            else
            {
                return new ValidationResult(true, null);
            }
        }
    }
}
public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MyViewModel();
        }
    }

29-验证提示自定义模板Validation.ErrorTemplate

验证提示的模板 为我们 可以自定义

<Window x:Class="WpfApp4.MainWindow"
        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:WpfApp4"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style x:Key="validateTextBoxStyle" TargetType="{x:Type TextBox}">
            <Setter Property="Width" Value="300" />
            <Setter Property="Height" Value="30" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="BorderBrush" Value="Red"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel VerticalAlignment="Center">
        <TextBox Style="{StaticResource validateTextBoxStyle}">
            <TextBox.Text>
                <Binding UpdateSourceTrigger="PropertyChanged" Path="WebSite">
                    <Binding.ValidationRules>
                        <local:HttpValidationRule/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
            <Validation.ErrorTemplate>
                <ControlTemplate>
                    <StackPanel Orientation="Horizontal">
                        <AdornedElementPlaceholder Name="customAdorner"></AdornedElementPlaceholder>
                        <TextBlock Text="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" Margin="10,0,0,0" VerticalAlignment="Center" Foreground="Red" >
                        </TextBlock>
                    </StackPanel>
                </ControlTemplate>
            </Validation.ErrorTemplate>
        </TextBox>
        <TextBox Width="300" Height="30" Margin="5"></TextBox>
    </StackPanel>
</Window>Code language: HTML, XML (xml)

30-错误提示增加红色图标

错误提示模板我们是可以随便定义的 里面可以使用布局控件 比如grid stackpanel等等。当然可以包含图片了。

<Validation.ErrorTemplate>
                <ControlTemplate>
                    <StackPanel Orientation="Horizontal">
                        <AdornedElementPlaceholder Name="customAdorner"></AdornedElementPlaceholder>
                        <Image Source="E:\更多--FoxDevelop\WPF进阶\ErrorNotify\ErrorNotify\cross-circle.png"/>
                        <TextBlock Text="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" Margin="10,0,0,0" VerticalAlignment="Center" Foreground="Red" >
                        </TextBlock>
                    </StackPanel>
                </ControlTemplate>
            </Validation.ErrorTemplate>Code language: HTML, XML (xml)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注