WPF自定义控件与样式(12)
- 格式:doc
- 大小:17.74 KB
- 文档页数:26
WPF⾃定义控件与样式(13)-⾃定义窗体Window⾃适应内容⼤⼩消息框MessageBox⼀.前⾔ 申明:WPF⾃定义控件与样式是⼀个系列⽂章,前后是有些关联的,但⼤多是按照由简到繁的顺序逐步发布的等,若有不明⽩的地⽅可以参考本系列前⾯的⽂章,⽂末附有部分⽂章链接。
本⽂主要内容:⾃定义Window窗体样式;基于⾃定义窗体实现⾃定义MessageBox消息提⽰框;⼆.⾃定义Window窗体样式 ⾃定义的Window窗体效果: 因为WPF默认的窗体⽐较简陋,⼤都需要⾃⼰实现Window窗体样式效果,基本思路很简单:第⼀步:⼲掉默认样式:WindowStyle = WindowStyle.None;第⼆步:设置窗体透明:AllowsTransparency = true;第三步:设置⾃⼰的窗体样式; 这样从外观样式上可以满⾜,但做为窗体该具备的基本功能还没有,需要另外来实现了:窗体Icon、标题栏(可以通过样式实现);窗体的基本按钮:最⼩化、最⼤化、关闭按钮;窗体的⿏标拖动;好像Win8、Win10的功能吧,窗体拖动到桌⾯边缘⾃动最⼤化、还原;⿏标调整窗⼝⼤⼩;双击标题栏最⼤化、还原; 上⾯的功能在本⽂中,⼀部分是⾃定义实现的,还有⼀部分是⽤了⼀个开源库(Microsoft.Windows.Shell)⽤于实现窗体⼤⼩、拖放等窗体基本功能,Microsoft.Windows.Shell⽂件下载:。
进⼊正题,⾃定义窗体WindowBase的后台C#代码:///<summary>/// WindowBase.xaml 的交互逻辑///</summary>public class WindowBase : Window{#region默认Header:窗体字体图标FIconpublic static readonly DependencyProperty FIconProperty =DependencyProperty.Register("FIcon", typeof(string), typeof(WindowBase), new PropertyMetadata("\ue62e"));///<summary>///按钮字体图标编码///</summary>public string FIcon{get { return (string)GetValue(FIconProperty); }set { SetValue(FIconProperty, value); }}#endregion#region默认Header:窗体字体图标⼤⼩public static readonly DependencyProperty FIconSizeProperty =DependencyProperty.Register("FIconSize", typeof(double), typeof(WindowBase), new PropertyMetadata(20D));///<summary>///按钮字体图标⼤⼩///</summary>public double FIconSize{get { return (double)GetValue(FIconSizeProperty); }set { SetValue(FIconSizeProperty, value); }}#endregion#region CaptionHeight 标题栏⾼度public static readonly DependencyProperty CaptionHeightProperty =DependencyProperty.Register("CaptionHeight", typeof(double), typeof(WindowBase), new PropertyMetadata(26D));///<summary>///标题⾼度///</summary>public double CaptionHeight{get { return (double)GetValue(CaptionHeightProperty); }SetValue(CaptionHeightProperty, value);//this._WC.CaptionHeight = value;}}#endregion#region CaptionBackground 标题栏背景⾊public static readonly DependencyProperty CaptionBackgroundProperty = DependencyProperty.Register("CaptionBackground", typeof(Brush), typeof(WindowBase), new PropertyMetadata(null));public Brush CaptionBackground{get { return (Brush)GetValue(CaptionBackgroundProperty); }set { SetValue(CaptionBackgroundProperty, value); }}#endregion#region CaptionForeground 标题栏前景景⾊public static readonly DependencyProperty CaptionForegroundProperty = DependencyProperty.Register("CaptionForeground", typeof(Brush), typeof(WindowBase), new PropertyMetadata(null));public Brush CaptionForeground{get { return (Brush)GetValue(CaptionForegroundProperty); }set { SetValue(CaptionForegroundProperty, value); }}#endregion#region Header 标题栏内容模板,以提⾼默认模板,可⾃定义public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(ControlTemplate), typeof(WindowBase), new PropertyMetadata(null));public ControlTemplate Header{get { return (ControlTemplate)GetValue(HeaderProperty); }set { SetValue(HeaderProperty, value); }}#endregion#region MaxboxEnable 是否显⽰最⼤化按钮public static readonly DependencyProperty MaxboxEnableProperty = DependencyProperty.Register("MaxboxEnable", typeof(bool), typeof(WindowBase), new PropertyMetadata(true));public bool MaxboxEnable{get { return (bool)GetValue(MaxboxEnableProperty); }set { SetValue(MaxboxEnableProperty, value); }}#endregion#region MinboxEnable 是否显⽰最⼩化按钮public static readonly DependencyProperty MinboxEnableProperty = DependencyProperty.Register("MinboxEnable", typeof(bool), typeof(WindowBase), new PropertyMetadata(true));public bool MinboxEnable{get { return (bool)GetValue(MinboxEnableProperty); }set { SetValue(MinboxEnableProperty, value); }}#endregionpublic WindowBase(){this.WindowStyle = WindowStyle.None;this.AllowsTransparency = true;this.WindowStartupLocation = WindowStartupLocation.CenterScreen;this.Style = this.FindResource("DefaultWindowStyle") as Style;this.Icon = Images.CreateImageSourceFromImage(Properties.Resources.logo);//12=6+6//Margin=6,Border.Effect.BlueRadius=6this.MaxHeight = SystemParameters.WorkArea.Height + 12 + 2;//bind commandthis.BindCommand(SystemCommands.CloseWindowCommand, this.CloseCommand_Execute);this.BindCommand(ApplicationCommands.Close, this.CloseCommand_Execute);this.BindCommand(SystemCommands.MaximizeWindowCommand, this.MaxCommand_Execute);this.BindCommand(SystemCommands.MinimizeWindowCommand, this.MinCommand_Execute);}private void CloseCommand_Execute(object sender, ExecutedRoutedEventArgs e){SystemCommands.CloseWindow(this);}private void MaxCommand_Execute(object sender, ExecutedRoutedEventArgs e){this.WindowState = this.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;e.Handled = true;}private void MinCommand_Execute(object sender, ExecutedRoutedEventArgs e){this.WindowState = WindowState.Minimized;e.Handled = true;}protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e){base.OnMouseLeftButtonDown(e);if (e.ButtonState == MouseButtonState.Pressed){this.DragMove();}View Code 绑定命令的扩展⽅法:///<summary>///绑定命令和命令事件到宿主UI///</summary>public static void BindCommand(this UIElement @ui, ICommand com, Action<object, ExecutedRoutedEventArgs> call){var bind = new CommandBinding(com);bind.Executed += new ExecutedRoutedEventHandler(call);@mandBindings.Add(bind);} WindowBase的样式有两个,⼀个是基础样式BaseWindowStyle,可以⾃定义头部标题栏,提供更多定制需求。
WPF⾃定义控件与样式-⾃定义按钮(Button)⼀、前⾔程序界⾯上的按钮多种多样,常⽤的就这⼏种:普通按钮、图标按钮、⽂字按钮、图⽚⽂字混合按钮。
本⽂章记录了不同样式类型的按钮实现⽅法。
⼆、固定样式的按钮固定样式的按钮⼀般在临时使⽤时或程序的样式⽐较固定时才会使⽤,按钮整体样式不需要做⼤的改动。
2.1 普通按钮-扁平化风格先看效果:定义Button的样式,详见代码:<Style x:Key="BtnInfoStyle" TargetType="Button"><Setter Property="Width" Value="70"/><Setter Property="Height" Value="25"/><Setter Property="Foreground" Value="White"/><Setter Property="BorderThickness" Value="0"/><Setter Property="Background" Value="#43a9c7"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="Button"><Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels <TextBlock Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/></Border><ControlTemplate.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter TargetName="border" Property="Background" Value="#2f96b4"/></Trigger><Trigger Property="IsPressed" Value="True"><Setter TargetName="border" Property="Background" Value="#2a89a4"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>引⽤⽅法:<Grid Background="White"><StackPanel Orientation="Horizontal" Margin="10" VerticalAlignment="Top"><Button Style="{StaticResource BtnInfoStyle}" Content="信息" Margin="5 0"/></Grid>上述代码实现了Button按钮的扁平化样式,如果你想调整颜⾊风格,通过修改Background的值可实现默认颜⾊,⿏标经过颜⾊以及⿏标按下颜⾊。
wpf templatebinding用法-回复WPF TemplateBinding用法指的是在WPF应用程序中,通过使用TemplateBinding将控件的属性与其模板中的其他元素绑定在一起。
它为我们提供了一种简单而强大的方式来创建可重用且灵活的用户界面。
TemplateBinding的作用是将控件的属性值绑定到其模板中的其他元素,以便在改变属性的同时,可以动态更新模板中的内容。
这种绑定机制使得我们可以根据控件的不同状态或者其他条件来改变其外观或者行为,从而满足不同的用户需求。
那么我们接下来一步一步地来回答关于WPF TemplateBinding用法的问题。
第一步:导入命名空间在开始使用TemplateBinding之前,我们需要导入WPF的命名空间。
一般情况下,我们需要在XAML文件的根元素中添加命名空间的引用。
例如:xaml<Window x:Class="WpfApp.MainWindow"xmlns="xmlns:x="xmlns:local="clr-namespace:WpfApp"Title="MainWindow" Height="450" Width="800">这里的local命名空间是我们的项目命名空间,用于引用自定义的控件和样式。
第二步:创建自定义控件接下来,我们需要创建一个自定义的控件,并在其模板中使用TemplateBinding。
这个自定义控件可以是任意的控件,比如Button、TextBlock等。
这里以Button为例,代码如下:csharppublic class CustomButton : Button{static CustomButton(){DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomButton), new FrameworkPropertyMetadata(typeof(CustomButton)));}}在上述代码中,我们创建了一个名为CustomButton的自定义控件,并使用了静态构造函数来设置默认样式。
wpf⾃定义控件(包含依赖属性以及事件)创建了这个依赖属性,就可以直接在对应的控件中使⽤了,就像是button中⼀开始就内置的width等属性⼀样,这个在设计⾃定义控件的时候⽤的尤其多下⾯讲的是⾃定义分页控件代码:<UserControl x:Class="WPFDataGridPaging.Pager"xmlns="/winfx/2006/xaml/presentation"xmlns:x="/winfx/2006/xaml"xmlns:mc="/markup-compatibility/2006"xmlns:d="/expression/blend/2008"xmlns:local="clr-namespace:WPFDataGridPaging"mc:Ignorable="d"d:DesignHeight="30" d:DesignWidth="220"><UserControl.Resources><Style TargetType="{x:Type Button}"><Setter Property="Width" Value="22"/><Setter Property="Height" Value="22"/></Style></UserControl.Resources><Grid><StackPanel Orientation="Horizontal"><Button x:Name="FirstPageButton" Margin="5,0" Click="FirstPageButton_Click"><Path Width="7" Height="10" Data="M0,0L0,10 M0,5L6,2 6,8 0,5" Stroke="Black" StrokeThickness="1"Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center"/></Button><Button x:Name="PreviousPageButton" Margin="0,0,5,0" Click="PreviousPageButton_Click"><Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center"/></Button><TextBlock VerticalAlignment="Center"><Run Text="第"/><Run x:Name="rCurrent" Text="0"/><Run Text="页"/></TextBlock><Button Margin="5,0" x:Name="NextPageButton" Click="NextPageButton_Click"><Path Width="8" Height="8" Data="M0,4L8,0 8,8z" Stroke="Black" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center"><Path.RenderTransform><RotateTransform Angle="180" CenterX="4" CenterY="4"/></Path.RenderTransform></Path></Button><Button Margin="0,0,5,0" x:Name="LastPageButton" Click="LastPageButton_Click"><Path x:Name="MainPath" Width="7" Height="10" Data="M0,0L0,10 M0,5 L6,2 6,8 0,5"Stroke="Black" StrokeThickness="1" Fill="Black" VerticalAlignment="Center" HorizontalAlignment="Center"><Path.RenderTransform><RotateTransform Angle="180" CenterX="3" CenterY="5"/></Path.RenderTransform></Path></Button><TextBlock VerticalAlignment="Center"><Run Text="共"/><Run x:Name="rTotal" Text="0"/><Run Text="页"/></TextBlock></StackPanel></Grid></UserControl>界⾯:后台代码:public partial class Pager : UserControl{#region声明事件和依赖属性public static RoutedEvent FirstPageEvent;public static RoutedEvent PreviousPageEvent;public static RoutedEvent NextPageEvent;public static RoutedEvent LastPageEvent;public static readonly DependencyProperty CurrentPageProperty;public static readonly DependencyProperty TotalPageProperty;#endregionpublic string CurrentPage{get { return (string)GetValue(CurrentPageProperty); }set { SetValue(CurrentPageProperty, value); }}public string TotalPage{get { return (string)GetValue(TotalPageProperty); }set { SetValue(TotalPageProperty, value); }}public Pager(){InitializeComponent();}static Pager(){#region注册事件以及依赖属性//注册FirstPageEvent事件,事件的拥有者是Pager,路由事件的名称是FirstPage,这是唯⼀的FirstPageEvent = EventManager.RegisterRoutedEvent("FirstPage", RoutingStrategy.Direct,typeof(RoutedEventHandler), typeof(Pager));PreviousPageEvent = EventManager.RegisterRoutedEvent("PreviousPage", RoutingStrategy.Direct,typeof(RoutedEventHandler), typeof(Pager));NextPageEvent = EventManager.RegisterRoutedEvent("NextPage", RoutingStrategy.Direct,typeof(RoutedEventHandler), typeof(Pager));LastPageEvent = EventManager.RegisterRoutedEvent("LastPage", RoutingStrategy.Direct,typeof(RoutedEventHandler), typeof(Pager));//注册⾃定义的依赖属性CurrentPageProperty = DependencyProperty.Register("CurrentPage",typeof(string), typeof(Pager), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnCurrentPageChanged))); TotalPageProperty = DependencyProperty.Register("TotalPage",typeof(string), typeof(Pager), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnTotalPageChanged)));#endregion}public event RoutedEventHandler FirstPage{add { AddHandler(FirstPageEvent, value); }remove { RemoveHandler(FirstPageEvent, value); }}public event RoutedEventHandler PreviousPage{add { AddHandler(PreviousPageEvent, value); }remove { RemoveHandler(PreviousPageEvent, value); }}public event RoutedEventHandler NextPage{add { AddHandler(NextPageEvent, value); }remove { RemoveHandler(NextPageEvent, value); }}public event RoutedEventHandler LastPage{add { AddHandler(LastPageEvent, value); }remove { RemoveHandler(LastPageEvent, value); }}///<summary>///依赖属性回调⽅法///</summary>///<param name="d"></param>///<param name="e"></param>public static void OnTotalPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){Pager p = d as Pager;if (p != null){Run rTotal = (Run)p.FindName("rTotal");rTotal.Text = (string)e.NewValue;}}private static void OnCurrentPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){Pager p = d as Pager;if (p != null){Run rCurrrent = (Run)p.FindName("rCurrent");rCurrrent.Text = (string)e.NewValue;}}private void FirstPageButton_Click(object sender, RoutedEventArgs e){RaiseEvent(new RoutedEventArgs(FirstPageEvent, this));}private void PreviousPageButton_Click(object sender, RoutedEventArgs e){RaiseEvent(new RoutedEventArgs(PreviousPageEvent, this));}private void NextPageButton_Click(object sender, RoutedEventArgs e){RaiseEvent(new RoutedEventArgs(NextPageEvent, this));}private void LastPageButton_Click(object sender, RoutedEventArgs e){RaiseEvent(new RoutedEventArgs(LastPageEvent, this));}}上⾯就是⾃定义的⼀个分页控件,如果我们想要使⽤这个控件,如下:<Window x:Class="WPFDataGridPaging.MainWindow"xmlns="/winfx/2006/xaml/presentation"xmlns:x="/winfx/2006/xaml"xmlns:d="/expression/blend/2008"xmlns:mc="/markup-compatibility/2006"xmlns:i="/expression/2010/interactivity"xmlns:local="clr-namespace:WPFDataGridPaging"mc:Ignorable="d"Title="MainWindow" Height="350" Width="525"><Grid><Grid.RowDefinitions><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><DataGrid Grid.Row="0" ItemsSource="{Binding FakeSource}" AutoGenerateColumns="False" CanUserAddRows="False"> <DataGrid.Columns><DataGridTextColumn Header="Item Id" Binding="{Binding Id}" Width="80"/><DataGridTextColumn Header="Item Name" Binding="{Binding ItemName}" Width="180"/></DataGrid.Columns></DataGrid><!-- TotalPage 和CurrentPage就是在Pager中⾃定义的依赖属性,可以在这⾥直接来⽤--><local:Pager TotalPage="{Binding TotalPage}"CurrentPage="{Binding CurrentPage, Mode=TwoWay}"HorizontalAlignment="Center"Grid.Row="1"><i:Interaction.Triggers><!--EventName="FirstPage" 这⾥FirstPage就是前⾯注册事件的时候默认的事件名称,必须要唯⼀ --><i:EventTrigger EventName="FirstPage"><i:InvokeCommandAction Command="{Binding FirstPageCommand}"/></i:EventTrigger><i:EventTrigger EventName="PreviousPage"><i:InvokeCommandAction Command="{Binding PreviousPageCommand}"/></i:EventTrigger><i:EventTrigger EventName="NextPage"><i:InvokeCommandAction Command="{Binding NextPageCommand}"/></i:EventTrigger><i:EventTrigger EventName="LastPage"><i:InvokeCommandAction Command="{Binding LastPageCommand}"/></i:EventTrigger></i:Interaction.Triggers></local:Pager></Grid></Window>界⾯:后台代码:///<summary>/// Interaction logic for MainWindow.xaml///</summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();//这⾥⼀定要注意,⼀定要将模型加到上下⽂中,要不然依赖属性和事件都不会触发,在实际开发中是不可能⼀打开 //界⾯就开始加载出来数据的,所以可以通过ObservableCollection形式绑定表格数据,//⽽需要绑定事件和依赖属性的需要将其绑定到上下⽂中DataContext = new MainViewModel();}}MainViewModel:public class MainViewModel : ViewModel{private ICommand _firstPageCommand;public ICommand FirstPageCommand{get{return _firstPageCommand;}set{_firstPageCommand = value;}}private ICommand _previousPageCommand;public ICommand PreviousPageCommand{get{return _previousPageCommand;}set{_previousPageCommand = value;}}private ICommand _nextPageCommand;public ICommand NextPageCommand{get{return _nextPageCommand;}set{_nextPageCommand = value;}}private ICommand _lastPageCommand;public ICommand LastPageCommand{get{return _lastPageCommand;}set{_lastPageCommand = value;}}private int _pageSize;public int PageSize{get{return _pageSize;}set{if(_pageSize != value){_pageSize = value;OnPropertyChanged("PageSize"); }}}private int _currentPage;public int CurrentPage{get{return _currentPage;}set{if(_currentPage != value){_currentPage = value;OnPropertyChanged("CurrentPage"); }}}private int _totalPage;public int TotalPage{get{return _totalPage;}set{if(_totalPage != value){_totalPage = value;OnPropertyChanged("TotalPage"); }}}///<summary>/// ObservableCollection表⽰⼀个动态数据集合,它可在添加、删除项⽬或刷新整个列表时提供通知。
WPF设置样式的⼏种⽅式第⼀种⽅式是直接使⽤Setter来进⾏,可以对Background等进⾏设置。
<Window.Resources><Style TargetType="Button"><Setter Property="Background" Value="Red"/></Style></Window.Resources>第⼆种是直接将⽐较复杂⼀点的Style放置到Window.Resources中:<Window.Resources><LinearGradientBrush x:Key="CheckedState" StartPoint="0,0" EndPoint="0,1"><GradientStop Color="#FFE7E1E1" Offset="0"/><GradientStop Color="black" Offset="1"/><GradientStop Color="gray" Offset="0.581"/></LinearGradientBrush></Window.Resources>使⽤的时候,直接利⽤ Background=”{StaticResource CheckedState}”即可。
第三种是利⽤Template⽅式来进⾏,这种可以进⾏⽐较复杂的样式制作:<Windowxmlns="/winfx/2006/xaml/presentation"xmlns:x="/winfx/2006/xaml"x:Class="WpfApplication4.MainWindow"x:Name="Window"Title="MainWindow"Width="640" Height="480"><Window.Resources><LinearGradientBrush x:Key="CheckedState" StartPoint="0,0" EndPoint="0,1"><GradientStop Color="#FFE7E1E1" Offset="0"/><GradientStop Color="black" Offset="1"/><GradientStop Color="gray" Offset="0.581"/></LinearGradientBrush><LinearGradientBrush x:Key="UnCheckedState" StartPoint="0,0" EndPoint="0,1"><GradientStop Color="#FFE7E1E1" Offset="0"/><GradientStop Color="gray" Offset="1"/><GradientStop Color="gray" Offset="0.581"/></LinearGradientBrush><Style TargetType="TabItem"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="TabItem"><Grid><Border Name="Border" BorderThickness="1" BorderBrush="Gray" Background="{StaticResource UnCheckedState}" Width="80" Height="25" Margin="0,0,1,0" CornerRadius="4,4,0,0"><Grid><ContentPresenter x:Name="ContentSite"VerticalAlignment="Center"HorizontalAlignment="Center"ContentSource="Header"Margin="12,2,12,2"RecognizesAccessKey="True"/></Grid></Border></Grid><ControlTemplate.Triggers><Trigger Property="IsSelected" Value="True"><Setter Property="Panel.ZIndex" Value="100"/><Setter TargetName="Border" Property="Background" Value="{StaticResource CheckedState}"/><Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0"/></Trigger><Trigger Property="IsEnabled" Value="False"><Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}"/><Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}"/><Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style></Window.Resources><Grid x:Name="LayoutRoot"><TabControl Margin="0,0,0,116"><TabControl.Resources><Style TargetType="TabPanel"><Setter Property="HorizontalAlignment" Value="Center"/></Style></TabControl.Resources><TabItem Header="TabItem">TabItem</TabItem><TabItem Header="My Item">My Item</TabItem><TabItem Header="My Database">My Database</TabItem><TabItem Header="TabItem"></TabItem><TabItem Header="TabItem"></TabItem><TabItem Header="TabItem"></TabItem></TabControl></Grid></Window>当然,制作出来的效果也就是好看⼀些,显⽰效果如下:。
目录一、wpfdevelopers 简介二、wpfdevelopers 的基本用法1. 创建wpfdevelopers 窗体2. 设置wpfdevelopers 窗体样式3. 添加控件和布局4. 数据绑定和事件处理三、wpfdevelopers 的高级用法1. 自定义控件和模板2. 动画和效果3. 多线程和异步操作四、wpfdevelopers 的优势和局限性五、总结一、wpfdevelopers 简介wpfdevelopers(Windows Presentation Foundation)是微软推出的一种用于创建桌面应用程序的技术框架,它基于.NET框架,采用XAML(Extensible Application Markup Language)作为界面设计语言。
wpfdevelopers 提供了丰富的图形和多媒体功能,支持复杂的界面布局和数据绑定,使开发人员能够轻松创建具有吸引力和交互性的应用程序。
二、wpfdevelopers 的基本用法1. 创建wpfdevelopers 窗体要使用wpfdevelopers 开发应用程序,首先需要创建一个wpfdevelopers 窗体。
可以通过Visual Studio等集成开发环境来创建wpfdevelopers 项目,并在项目中添加wpfdevelopers 窗体。
wpfdevelopers 窗体继承自Window类,可以在XAML文件中定义窗体的外观和布局,也可以在Code-behind文件中编写窗体的行为和逻辑。
以下是一个简单的wpfdevelopers 窗体的XAML代码:```<Window x:Class="MyWpfApp.M本人nWindow"xmlns="网络协议xxx"xmlns:x="网络协议xxx"Title="MyWpfApp" Height="350" Width="525"><Grid><!-- 在这里添加控件和布局 --></Grid></Window>```2. 设置wpfdevelopers 窗体样式wpfdevelopers 提供了丰富的样式和模板功能,可以通过样式来统一窗体和控件的外观,也可以通过模板来自定义控件的外观和行为。
wpf 关闭窗体按钮的样式在WPF(Windows Presentation Foundation)中,关闭窗体按钮的样式通常可以通过自定义Window的ControlTemplate或使用XAML样式来实现。
这里我将详细解释如何自定义关闭按钮的样式,以确保其与您的应用程序的整体设计相协调。
首先,您可以通过编辑Window的ControlTemplate来更改关闭按钮的外观。
在XAML 中,您可以为Window定义一个样式,并在其中设置ControlTemplate。
在这个模板中,您可以找到表示关闭按钮的部分,并对其进行自定义。
例如,您可以更改关闭按钮的形状、颜色和大小。
您可以使用Path元素来定义按钮的形状,并使用Stroke和Fill属性来设置其颜色和填充。
您还可以添加鼠标悬停和点击时的视觉效果,以提供更好的用户体验。
另外,如果您想要更加灵活地控制关闭按钮的样式,您可以考虑使用自定义控件。
您可以创建一个继承自Button的控件,并在其中定义自己的样式和行为。
然后,您可以将这个自定义控件添加到Window的ControlTemplate中,以替换默认的关闭按钮。
除了样式之外,您还可以考虑添加一些动画效果来增强关闭按钮的交互性。
例如,当鼠标悬停在按钮上时,您可以使用Storyboard来创建一个平滑的动画效果,以改变按钮的大小、颜色或形状。
总之,在WPF中自定义关闭窗体按钮的样式需要一定的XAML和样式设计知识。
通过编辑Window的ControlTemplate或使用自定义控件,您可以实现高度个性化的关闭按钮样式,以提升您的应用程序的用户界面体验。
记得在自定义样式时考虑可访问性和用户体验,确保按钮的功能性和易用性。
WPF样式(Style)与模板(Template)⼀、WPF样式类似于Web应⽤程序中的CSS,在WPF中可以为控件定义统⼀的样式(Style)。
样式属于资源的⼀种,例如为Button定义统⼀的背景颜⾊和字体:1: <Window.Resources>2: <Style3: TargetType="Button">4: <Setter Property="Background" Value="Yellow" />5: <Setter Property="Margin" Value="5" />6: <Setter Property="FontFamily" Value="Comic Sans MS"/>7: <Setter Property="FontSize" Value="14"/>8: </Style>9: </Window.Resources>10: <StackPanel>11: <Button>Button A</Button>12: <Button Foreground="Red" Background="White">Button B</Button>13: </StackPanel>从执⾏的结果上来看:在Style中定义的属性及值,影响到Window中的所有类型为Button的控件的样式在Button中可以新定义其他属性(如Foreground),覆盖Style中的定义(Background)这种样式,类似于CSS中的类型选择器,为某种类型定义样式。
WPF入门教程系列在这个WPF入门教程系列中,我们将探索WPF的基础知识,并通过一些简单的示例来演示如何创建一个基本的WPF应用程序。
1. 了解XAML(eXtensible Application Markup Language)2.创建一个简单的WPF应用程序3.管理用户界面元素在这个教程中,我们将学习如何管理用户界面元素,包括如何设置元素的属性、如何响应用户的操作以及如何使用命令来处理事件。
4.使用数据绑定数据绑定是WPF中一个重要的概念,它可以将数据源与用户界面元素进行连接,使得数据的变化可以自动反映在界面上。
在这个教程中,我们将学习如何使用数据绑定来将数据源与界面元素进行关联。
5.用样式和模板自定义界面样式和模板是WPF中用于自定义用户界面外观的重要特性。
在这个教程中,我们将学习如何创建和应用样式和模板,来改变界面元素的外观。
6.创建自定义的用户界面控件在这个教程中,我们将学习如何创建自定义的用户界面控件,以满足特定的应用程序需求。
我们将了解如何定义控件的外观和行为,并将其添加到我们的应用程序中。
7.使用动画和转换动画和转换是WPF中用于创建生动和交互式用户界面的重要特性。
在这个教程中,我们将学习如何使用动画和转换来改变界面元素的位置、大小、颜色等属性。
8.处理多媒体和图形WPF具有强大的图形和多媒体处理能力,可以用于创建各种各样的视觉效果和交互体验。
在这个教程中,我们将学习如何在WPF应用程序中使用多媒体和图形。
这个WPF入门教程系列将为你提供一个全面的了解WPF的基础知识,并通过实际的示例来演示如何创建一个基本的WPF应用程序。
希望它能帮助你入门WPF,并为你在使用WPF开发应用程序时提供指导。
WPF⾃定义漂亮的按钮样式⾸先打开 Microsoft Visual Studio 2008 ,新建⼀个WPF项⽬,在上⾯随便放⼏个按钮:然后给各个按钮设置不同的背景颜⾊:设置好之后就是这样啦:然后我们就开始在 App.xaml ⽂件中定义按钮样式了:定义的样式代码如下:以下为引⽤的内容:<Application x:Class="WPFButton.App"xmlns=""xmlns:x=""StartupUri="Window1.xaml"><Application.Resources><!--定义按钮样式--><Style TargetType="Button"><Setter Property="Foreground" Value="Black"/><!--修改模板属性--><Setter Property="Template"><Setter.Value><!--控件模板--><ControlTemplate TargetType="Button"><!--背景⾊--><Border x:Name="back" Opacity="0.8" CornerRadius="3"><Border.BitmapEffect><OuterGlowBitmapEffect Opacity="0.7" GlowSize="0" GlowColor="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Button.Background).(SolidColorBrush.Color)}" /></Border.BitmapEffect><Border.Background><LinearGradientBrush StartPoint="0,0" EndPoint="0,1.5"><GradientBrush.GradientStops><GradientStopCollection><GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Button.Background).(SolidColorBrush.Color)}" Offset="0"/><GradientStop Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Button.Background).(SolidColorBrush.Color)}" Offset="0.4"/><GradientStop Color="#FFF" Offset="1"/></GradientStopCollection></GradientBrush.GradientStops></LinearGradientBrush></Border.Background><!--前景⾊及边框--><Border x:Name="fore" BorderThickness="1" CornerRadius="3" BorderBrush="#5555"><Border.Background><LinearGradientBrush StartPoint="0,0" EndPoint="0,1"><GradientBrush.GradientStops><GradientStopCollection><GradientStop Color="#6FFF" Offset="0.5"/><GradientStop Color="#1111" Offset="0.51"/></GradientStopCollection></GradientBrush.GradientStops></LinearGradientBrush></Border.Background><!--按钮内容--><ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center" Content=" {TemplateBinding Content}"><ContentPresenter.BitmapEffect><DropShadowBitmapEffect Color="#000" Direction="-90" ShadowDepth="2" Softness="0.1" Opacity="0.3" /><DropShadowBitmapEffect Color="#000" Direction="-90" ShadowDepth="2" Softness="0.1" Opacity="0.3" /> </ContentPresenter.BitmapEffect></ContentPresenter></Border></Border><!--触发器--><ControlTemplate.Triggers><!--⿏标移⼊移出--><Trigger Property="IsMouseOver" Value="True"><Trigger.EnterActions><BeginStoryboard><Storyboard><DoubleAnimation To="6" Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty=" (Border.BitmapEffect).(OuterGlowBitmapEffect.GlowSize)" /><ColorAnimation To="#AFFF" BeginTime="0:0:0.2" Duration="0:0:0.2" Storyboard.TargetName="fore" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" /><ColorAnimation To="#3FFF" BeginTime="0:0:0.2" Duration="0:0:0.2" Storyboard.TargetName="fore" Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" /></Storyboard></BeginStoryboard></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard><Storyboard><DoubleAnimation Duration="0:0:0.2" Storyboard.TargetName="back" Storyboard.TargetProperty=" (Border.BitmapEffect).(OuterGlowBitmapEffect.GlowSize)" /><ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="fore" Storyboard.TargetProperty=" (Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" /><ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="fore" Storyboard.TargetProperty=" (Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" /></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger><!--按钮按下弹起--><Trigger Property="IsPressed" Value="True"><Trigger.EnterActions><BeginStoryboard><Storyboard><DoubleAnimation To="3" Duration="0:0:0.1" Storyboard.TargetName="back" Storyboard.TargetProperty=" (Border.BitmapEffect).(OuterGlowBitmapEffect.GlowSize)" /><ColorAnimation To="#3AAA" Duration="0:0:0.1" Storyboard.TargetName="fore"Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" /><ColorAnimation To="#2111" Duration="0:0:0.1" Storyboard.TargetName="fore"Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" /></Storyboard></BeginStoryboard></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard><Storyboard><DoubleAnimation Duration="0:0:0.1" Storyboard.TargetName="back" Storyboard.TargetProperty=" (Border.BitmapEffect).(OuterGlowBitmapEffect.GlowSize)" /><ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="fore" Storyboard.TargetProperty=" (Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" /><ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="fore" Storyboard.TargetProperty=" (Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" /></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger><!--按钮失效--><Trigger Property="IsEnabled" Value="False"><Setter Property="Foreground" Value="#B444"/><Trigger.EnterActions><BeginStoryboard><BeginStoryboard><Storyboard><DoubleAnimation To="0" Duration="0:0:0.3" Storyboard.TargetName="back" Storyboard.TargetProperty=" (Border.BitmapEffect).(OuterGlowBitmapEffect.GlowSize)" /><DoubleAnimation To="1" Duration="0:0:0.1" Storyboard.TargetName="content"Storyboard.TargetProperty="(ContentPresenter.BitmapEffect).(DropShadowBitmapEffect.Opacity)" /><DoubleAnimation To="-135" Duration="0:0:0.1" Storyboard.TargetName="content"Storyboard.TargetProperty="(ContentPresenter.BitmapEffect).(DropShadowBitmapEffect.Direction)" /><ColorAnimation To="#FFF" Duration="0:0:0.3" Storyboard.TargetName="content"Storyboard.TargetProperty="(ContentPresenter.BitmapEffect).(DropShadowBitmapEffect.Color)" /><ColorAnimation To="#D555" Duration="0:0:0.3" Storyboard.TargetName="fore"Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" /><ColorAnimation To="#CEEE" Duration="0:0:0.3" Storyboard.TargetName="fore"Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" /><ColorAnimation To="#CDDD" Duration="0:0:0.3" Storyboard.TargetName="fore"Storyboard.TargetProperty="(Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" /></Storyboard></BeginStoryboard></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard><Storyboard><DoubleAnimation Duration="0:0:0.1" Storyboard.TargetName="back" Storyboard.TargetProperty=" (Border.BitmapEffect).(OuterGlowBitmapEffect.GlowSize)" /><DoubleAnimation Duration="0:0:0.1" Storyboard.TargetName="content" Storyboard.TargetProperty=" (ContentPresenter.BitmapEffect).(DropShadowBitmapEffect.Opacity)" /><DoubleAnimation Duration="0:0:0.1" Storyboard.TargetName="content" Storyboard.TargetProperty=" (ContentPresenter.BitmapEffect).(DropShadowBitmapEffect.Direction)" /><ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="content" Storyboard.TargetProperty=" (ContentPresenter.BitmapEffect).(DropShadowBitmapEffect.Color)" /><ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="fore" Storyboard.TargetProperty=" (Border.BorderBrush).(SolidColorBrush.Color)" /><ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="fore" Storyboard.TargetProperty=" (Border.Background).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)" /><ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="fore" Storyboard.TargetProperty=" (Border.Background).(LinearGradientBrush.GradientStops)[1].(GradientStop.Color)" /></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style></Application.Resources></Application>看了先不要头⼤,我们先看看最终效果,然后回过头来再解释代码:这是常规样式这个是⿏标移到上⾯时的样式这个是⿏标点击时的样式还有就是按钮失效时的样式效果还算不错吧,下⾯来讲解代码喽,头晕的同学可以现在就收拾东西回家了哈。
WPF如何⾃定义TabControl控件样式⽰例详解⼀、前⾔程序中经常会⽤到TabControl控件,默认的控件样式很普通。
⽽且样式或功能不⼀定符合我们的要求。
⽐如:我们需要TabControl的标题能够居中、或平均分布;或者我们希望TabControl的标题能够进⾏关闭。
要实现这些功能我们需要对TabControl的样式进⾏定义。
⼆、实现TabControl的标题平均分布默认的TabControl标题是使⽤TabPanel容器包含的。
要想实现TabControl标题头平均分布,需要把TabPanel替换成UniformGrid;替换后的TabControl样式如下:<Style x:Key="TabControlStyle" TargetType="{x:Type TabControl}"><Setter Property="Padding" Value="2"/><Setter Property="HorizontalContentAlignment" Value="Center"/><Setter Property="VerticalContentAlignment" Value="Center"/><Setter Property="Background" Value="White"/><Setter Property="BorderBrush" Value="#FFACACAC"/><Setter Property="BorderThickness" Value="1"/><Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type TabControl}"><Grid x:Name="templateRoot" ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local"><Grid.ColumnDefinitions><ColumnDefinition x:Name="ColumnDefinition0"/><ColumnDefinition x:Name="ColumnDefinition1" Width="0"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition x:Name="RowDefinition0" Height="Auto"/><RowDefinition x:Name="RowDefinition1" Height="*"/></Grid.RowDefinitions><UniformGrid x:Name="HeaderPanel" Rows="1" Background="Transparent" Grid.Column="0" IsItemsHost="True" Margin="0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/><Line X1="0" X2="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" Stroke="White" StrokeThickness="0.1" VerticalAlignment="Bottom" Margin="0 0 0 1" SnapsToDevicePixels="True"/><Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" <ContentPresenter x:Name="PART_SelectedContentHost" ContentTemplate="{TemplateBinding SelectedContentTemplate}" Content="{TemplateBinding SelectedContent}" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentSou </Border></Grid><ControlTemplate.Triggers><Trigger Property="TabStripPlacement" Value="Bottom"><Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/><Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/><Setter Property="Height" TargetName="RowDefinition0" Value="*"/><Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/></Trigger><Trigger Property="TabStripPlacement" Value="Left"><Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/><Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/><Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/><Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/><Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/><Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/><Setter Property="Height" TargetName="RowDefinition0" Value="*"/><Setter Property="Height" TargetName="RowDefinition1" Value="0"/></Trigger><Trigger Property="TabStripPlacement" Value="Right"><Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/><Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/><Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/><Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/><Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/><Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/><Setter Property="Height" TargetName="RowDefinition0" Value="*"/><Setter Property="Height" TargetName="RowDefinition1" Value="0"/></Trigger><Trigger Property="IsEnabled" Value="False"><Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>即使这样设置了,TabControl的标题还是很丑,这个时候就需要通过设置TabItem来更改标题样式了。
wpf controltemplate和contenttemplate在WPF(Windows Presentation Foundation)中,`ControlTemplate`和`ContentTemplate`是两个重要的概念,用于自定义控件的外观和内容。
`ControlTemplate`用于定义控件的整体外观和行为。
它可以定义控件的视觉元素,如背景、边框、文本等,并定义控件的交互行为,如鼠标点击、键盘输入等。
通过使用`ControlTemplate`,可以为现有的控件提供自定义的外观,或者创建全新的自定义控件。
例如,假设有一个按钮控件,默认的外观可能不符合应用程序的设计需求。
可以创建一个自定义的`ControlTemplate`,重新定义按钮的外观,例如更改背景颜色、添加图标等。
这样,在应用程序中使用这个自定义的按钮控件时,它将显示自定义的外观。
`ContentTemplate`则用于定义控件的内容。
它指定了控件内部显示的内容,通常是数据或子元素。
通过使用`ContentTemplate`,可以根据不同的数据或条件,动态地显示不同的内容。
例如,有一个列表框控件,需要根据不同的项显示不同的样式。
可以为每个项定义一个自定义的`DataTemplate`,并在`ContentTemplate`中引用这些`DataTemplate`。
这样,当添加项到列表框时,它们将根据相应的`DataTemplate`进行显示。
总的来说,`ControlTemplate`用于定义控件的外观和行为,而`ContentTemplate`用于定义控件的内容显示。
两者结合使用,可以实现高度自定义的控件和动态的内容显示。
在 WPF 中,使用`ControlTemplate`和`ContentTemplate`需要了解 XAML(eXtensible Application Markup Language)标记语言和 WPF 的模板语法。
WPF⾃定义控件创建本⽂简单的介绍⼀下WPF⾃定义控件的开发。
⾸先,我们打开VisualStudio创建⼀个WPF⾃定义控件库,如下图:然后,我们可以看到创建的解决⽅案如下:在解决⽅案中,我们看到了⼀个Themes⽂件夹和⼀个CS⽂件。
其中CS⽂件,就是我们需要编写的⾃定义控件,⾥⾯的类继承了Control类;⽽Themes则存放该控件的样式。
即,WPF⾃定义控件,是通过样式给我们的编辑的控件类披上外⾐⽽形成的。
下⾯,我们来编写⼀个简单的时间控件。
我们先将CustomControl1⽂件改名为KibaDateTime,然后打开KibaDateTime.cs⽂件,看到了⼀些控件应⽤提⽰,这些提⽰写的是⾃定义控件的应⽤⽅式,我们先不看这些提⽰,因为他写的不是很好理解。
接下来我们开始编写时间控件,修改KibaDateTime类如下:public class KibaDateTime : TextBox{private static Regex regex = new Regex("[0-9]+");#region ⼩时public static readonly DependencyProperty HourProperty = DependencyProperty.Register("Hour", typeof(int), typeof(KibaDateTime), new FrameworkPropertyMetadata(00));public int Hour{get{return (int)GetValue(HourProperty);}set{SetValue(HourProperty, value);}}#endregion#region 分钟public static readonly DependencyProperty MinuteProperty = DependencyProperty.Register("Minute", typeof(int), typeof(KibaDateTime), new FrameworkPropertyMetadata(00));public int Minute{get{return (int)GetValue(MinuteProperty);}set{SetValue(MinuteProperty, value);}}#endregion#region 秒public static readonly DependencyProperty SecondProperty = DependencyProperty.Register("Second", typeof(int), typeof(KibaDateTime), new FrameworkPropertyMetadata(00));public int Second{get{return (int)GetValue(SecondProperty);}set{SetValue(SecondProperty, value);}}#endregionstatic KibaDateTime(){//当此依赖项属性位于指定类型的实例上时为其指定替换元数据,以在该依赖项属性继承⾃基类型时重写该属性已存在的元数据。
wpf 教程WPF教程是一个逐步教你使用WPF(Windows Presentation Foundation)开发应用程序的指南。
WPF是一个用于创建现代化、交互式和美观的Windows应用程序界面的框架。
本教程将帮助你了解WPF的核心概念和基本技术,并教你如何使用这些技术创建功能丰富的界面。
以下是本教程的主要内容:1. 概述WPF:介绍WPF的背景和特点,以及为何选择使用它开发应用程序。
2. XAML基础:学习如何使用XAML(可扩展应用程序标记语言)创建WPF界面,并了解XAML的语法和常用元素。
3. 布局和控件:探索WPF的布局系统和常用控件,包括面板、容器和输入控件。
了解如何使用这些控件创建自适应布局和响应式界面。
4. 数据绑定:学习如何使用数据绑定将数据与界面元素关联起来,并实现数据的双向同步。
5. 样式和模板:了解如何使用样式和模板来自定义控件的外观和行为,并实现视觉一致的界面。
6. 事件和命令:学习如何使用事件和命令处理用户交互和响应,以及如何实现路由事件和自定义命令。
7. 动画和转换:探索WPF的动画和转换功能,实现界面元素的平滑过渡和动态效果。
8. 数据访问和数据库:了解如何在WPF应用程序中使用数据访问技术,包括使用和Entity Framework访问数据库。
9. MVVM设计模式:介绍MVVM(模型-视图-视图模型)设计模式,并展示如何在WPF应用程序中应用该模式以实现松耦合和可测试性。
通过跟随这个教程,你将会掌握WPF的核心概念和技术,能够独立开发功能强大的Windows应用程序界面。
立即开始吧!。
WPF⾃定义控件与样式(3)-TextBoxRichTextBoxPasswordBox样。
⼀.前⾔.预览 申明:WPF⾃定义控件与样式是⼀个系列⽂章,前后是有些关联的,但⼤多是按照由简到繁的顺序逐步发布的等,若有不明⽩的地⽅可以参考本系列前⾯的⽂章,⽂末附有部分⽂章链接。
本⽂主要是对⽂本输⼊控件进⾏样式开发,及相关扩展功能开发,主要内容包括:基本⽂本框TextBox控件样式及扩展功能,实现了样式、⽔印、Label标签、功能扩展;富⽂本框RichTextBox控件样式;密码输⼊框PasswordBox控件样式及扩展功能;效果图:⼆.基本⽂本框TextBox控件样式及扩展功能2.1 TextBox基本样式样式代码如下:<!--TextBox默认样式--><Style TargetType="{x:Type TextBox}" x:Key="DefaultTextBox"><Setter Property="ContextMenu" Value="{DynamicResource TextBoxContextMenu}"/><Setter Property="SelectionBrush" Value="{StaticResource TextSelectionBrush}"/><Setter Property="FontFamily" Value="{StaticResource FontFamily}"/><Setter Property="FontSize" Value="{StaticResource FontSize}"/><Setter Property="BorderThickness" Value="1"/><Setter Property="MinHeight" Value="26"/><Setter Property="Width" Value="100"/><Setter Property="Background" Value="{StaticResource TextBackground}"/><Setter Property="Foreground" Value="{StaticResource TextForeground}"/><Setter Property="Padding" Value="0"/><Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}"/><Setter Property="local:ControlAttachProperty.FocusBorderBrush" Value="{StaticResource FocusBorderBrush}"/><Setter Property="local:ControlAttachProperty.MouseOverBorderBrush" Value="{StaticResource MouseOverBorderBrush}"/><Setter Property="VerticalContentAlignment" Value="Center"/><!-- change SnapsToDevicePixels to True to view a better border and validation error --><Setter Property="SnapsToDevicePixels" Value="True"/><!--英 ['kærət] 美 ['kærət] 插⼊符号--><Setter Property="CaretBrush" Value="{StaticResource TextForeground}"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type TextBox}"><Grid x:Name="PART_Root"><Border x:Name="Bg" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"CornerRadius="{TemplateBinding local:ControlAttachProperty.CornerRadius}"BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"/> <Grid x:Name="PART_InnerGrid"><Grid.ColumnDefinitions><ColumnDefinition Width="Auto"/><ColumnDefinition Width="*"/><ColumnDefinition Width="Auto"/></Grid.ColumnDefinitions><!--Label区域--><ContentControl x:Name="Label" Margin="1" Template="{TemplateBinding local:belTemplate}"Content="{TemplateBinding local:bel}"/><!--内容区域--><ScrollViewer x:Name="PART_ContentHost" BorderThickness="0" Grid.Column="1" IsTabStop="False" Margin="2"VerticalAlignment="Stretch" Background="{x:Null}"/><!--⽔印--><TextBlock x:Name="Message" Padding="{TemplateBinding Padding}" Visibility="Collapsed"Text="{TemplateBinding local:ControlAttachProperty.Watermark}" Grid.Column="1"Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="{StaticResource WatermarkOpacity}"HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="5,2,5,2"/><!--附加内容区域--><Border x:Name="PART_AttachContent" Grid.Column="2" Margin="2" VerticalAlignment="Center" HorizontalAlignment="Center"><ContentControl VerticalAlignment="Center" VerticalContentAlignment="Center" Template="{TemplateBinding local:ControlAttachProperty.AttachContent}"/></Border></Grid></Grid><ControlTemplate.Triggers><!--显⽰⽔印--><DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text}" Value=""><Setter TargetName="Message" Property="Visibility" Value="Visible"/></DataTrigger><Trigger Property="IsMouseOver" Value="True"><Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.MouseOverBorderBrush),RelativeSource={RelativeSource Self}}"/></Trigger><Trigger Property="IsFocused" Value="True"><Setter Property="BorderBrush" Value="{Binding Path=(local:ControlAttachProperty.FocusBorderBrush),RelativeSource={RelativeSource Self}}"/></Trigger><!--不可⽤--><Trigger Property="IsEnabled" Value="False"><Setter TargetName="PART_Root" Property="Opacity" Value="{StaticResource DisableOpacity}"/></Trigger><!--只读时,禁⽤PART_AttachContent--><Trigger Property="IsReadOnly" Value="True"><Setter TargetName="PART_AttachContent" Property="IsEnabled" Value="False"/><Setter TargetName="Bg" Property="Opacity" Value="{StaticResource ReadonlyOpacity}"/><Setter TargetName="PART_ContentHost" Property="Opacity" Value="{StaticResource ReadonlyOpacity}"/><Setter TargetName="Label" Property="Opacity" Value="{StaticResource ReadonlyOpacity}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style> 模板内容主要包含四部分:⽤于实现Label标签的预留区域;TextBox本⾝的⽂本输⼊显⽰部分;⽔印显⽰部分;功能扩展的预留区域; 其中Label标签、功能扩展,还有输⼊框的不同状态显⽰效果都是通过附加属性来实现的,其实从本质上附加属性和控件上定义的依赖属性是同⼀个概念,有些时候附加属性会更加⽅便,对于⼀些可共⽤的属性,就⽐较⽅便,这⼀点怎本⽂是有体现的。
WPF滑块控件(Slider)的⾃定义样式前⾔每次开发滑块控件的样式都要花很久去读样式代码,感觉有点记不牢,所以特此备忘。
⾃定义滑块样式⾸先创建项⽬,添加Slider控件。
然后获取Slider的Window样式,如下图操作。
然后弹出界⾯如下.我们点击确定。
点击确定后,我们的页⾯的Resources中,增加了⼀系列样式代码,⽽滑块代码会被修改为如下样⼦:可以看到,系统为我们的Slider控件增加了样式——Style="{DynamicResource SliderStyle1}"现在我们查看样式SliderStyle1,F12跟踪到定义。
上述代码中我们可以看发现Slider使⽤的模板是SliderHorizontal,但当他的排列⽅向为Vertical时,则使⽤SliderVertical模板。
因为Slider控件默认是横向布局,所以我们先修改SliderHorizontal模板,对Slider进⾏下美化。
同样,我们继续F12跟进SliderHorizontal的定义。
SliderHorizontal模板的定义⽐较多,这⾥直接定义到重点内容——轨道。
⾸先定位到代码【Border x:Name="TrackBackground"】,这⾥的TrackBackground是控制滑块背景颜⾊的,我们修改其背景颜⾊和边框颜⾊。
得到效果如下:但我们有时候需要拖动前后颜⾊不⼀样,此时就靠背景修改就不够了。
在SliderHorizontal模板中找到DecreaseRepeatButton和IncreaseRepeatButton;这两个⼀个是拖动前覆盖颜⾊,⼀个是拖动后覆盖颜⾊。
修改代码如下:得到效果如下:注意这⾥的Height⼀定要给值。
现在,我们设置好了轨道,可当前的滑块的颜⾊我们有点不太满意,所以我们再来处理下滑块。
滑块模板的模板是上⽅代码中粉⾊标记的代码——Thumb。
WPF自定义控件与样式(12)WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表时间2015-12-01 09:21:00博客园-原创精华区原文/anding/p/5009120.html主题WPFBitmap一.前言申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接。
本文主要针对WPF项目开发中图片的各种使用问题,经过总结,把一些经验分享一下。
内容包括:WPF常用图像数据源ImageSource的创建;自定义缩略图控件ThumbnailImage,支持网络图片、大图片、图片异步加载等特性;动态图片gif播放控件;图片列表样式,支持大数据量的虚拟化;二.WPF常用图像数据源ImageSource的创建<Image Source="../Images/qq.png"></Image>这是一个普通Image控件的使用,Source的数据类型是ImageSource,在XAML中可以使用文件绝对路径或相对路径,ImageSource是一个抽象类,我们一般使用BitmapSource、BitmapImage等。
但在实际项目中,有各种各样的需求,比如:从Bitmap创建ImageSource对象;从数据流byte[]创建ImageSource对象;从System.Drawing.Image创建ImageSource对象;从一个大图片文件创建一个指定大小的ImageSource对象;2.1 从System.Drawing.Image创建指定大小ImageSource 对象/// <summary>/// 使用System.Drawing.Image创建WPF使用的ImageSource类型缩略图(不放大小图)/// </summary>/// <paramname="sourceImage">System.Drawing.Image 对象</param>/// <param name="width">指定宽度</param> /// <param name="height">指定高度</param> public static ImageSource CreateImageSourceThumbnia(System.Drawing.Image sourceImage, double width, double height){if (sourceImage == null) return null;double rw = width / sourceImage.Width;double rh = height / sourceImage.Height;var aspect = (float)Math.Min(rw, rh);int w = sourceImage.Width, h = sourceImage.Height;if (aspect < 1){w = (int)Math.Round(sourceImage.Width * aspect); h = (int)Math.Round(sourceImage.Height * aspect);}Bitmap sourceBmp = new Bitmap(sourceImage, w, h); IntPtr hBitmap = sourceBmp.GetHbitmap(); BitmapSource bitmapSource =Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions()); bitmapSource.Freeze();System.Utility.Win32.Win32.DeleteObject(hBitmap); sourceImage.Dispose();sourceBmp.Dispose();return bitmapSource;}2.2 从一个大图片文件创建一个指定大小的ImageSource对象/// <summary>/// 创建WPF使用的ImageSource类型缩略图(不放大小图)/// </summary>/// <param name="fileName">本地图片路径</param>/// <param name="width">指定宽度</param>/// <param name="height">指定高度</param> public static ImageSource CreateImageSourceThumbnia(string fileName, double width, double height){System.Drawing.Image sourceImage =System.Drawing.Image.FromFile(fileName);double rw = width / sourceImage.Width;double rh = height / sourceImage.Height;var aspect = (float)Math.Min(rw, rh);int w = sourceImage.Width, h = sourceImage.Height;if (aspect < 1){w = (int)Math.Round(sourceImage.Width * aspect); h = (int)Math.Round(sourceImage.Height * aspect);}Bitmap sourceBmp = new Bitmap(sourceImage, w, h); IntPtr hBitmap = sourceBmp.GetHbitmap(); BitmapSource bitmapSource =Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions()); bitmapSource.Freeze();System.Utility.Win32.Win32.DeleteObject(hBitmap); sourceImage.Dispose();sourceBmp.Dispose();return bitmapSource;}2.3 从Bitmap创建指定大小的ImageSource对象/// <summary>/// 从一个Bitmap创建ImageSource/// </summary>/// <param name="image">Bitmap对象</param>/// <returns></returns>public static ImageSource CreateImageSourceFromImage(Bitmap image){if (image == null) return null;try{IntPtr ptr = image.GetHbitmap();BitmapSource bs =Imaging.CreateBitmapSourceFromHBitmap(ptr, IntPtr.Zero, Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions());bs.Freeze();image.Dispose();System.Utility.Win32.Win32.DeleteObject(ptr);return bs;}catch (Exception){return null;}}2.4 从数据流byte[]创建指定大小的ImageSource对象/// <summary>/// 从数据流创建缩略图/// </summary>public static ImageSource CreateImageSourceThumbnia(byte[] data, double width, double height){using (Stream stream = new MemoryStream(data, true)) {using (Image img = Image.FromStream(stream)){return CreateImageSourceThumbnia(img, width, height);}}}三.自定义缩略图控件ThumbnailImage ThumbnailImage控件的主要解决的问题:为了能扩展支持多种类型的缩略图,设计了一个简单的模式,用VS自带的工具生成的代码视图:3.1 多种类型的缩略图扩展首先定义一个图片类型枚举:/// <summary>/// 缩略图数据源源类型/// </summary>public enum EnumThumbnail{Image,Vedio,WebImage,Auto,FileX,}然后定义了一个接口,生成图片数据源ImageSource/// <summary>/// 缩略图创建服务接口/// </summary>public interface IThumbnailProvider{/// <summary>/// 创建缩略图。