WPF-基础及进阶扩展合集(持续更新)

目录

一、基础

1、GridSplitter分割线

2、x:static访问资源文件

3、wpf触发器

4、添加xaml资源文件

5、Convert转换器

6、多路绑定与多路转换器

二、进阶扩展

1、HierarchicalDataTemplate

2、XmlDataProvider从外部文件获取源

3、TextBox在CellTemplate中的焦点问题

4、让窗体可裁减

5_1、获取DataGrid的ScrollViewer

5_2、DataGrid绑定集合改变触发事件

5_3、ScrollViewer自动滚动到尾部

6、wpf的Behavior行为

8、Cursor光标属性

9、ListView布局、滚动条

10、DataGrid文本过长换行

11、指定字体集FontFamily

12、窗体可拖动

13、虚拟化技术提升程序性能

14、查看Binding错误信息

15、DataGrid模板列中Button绑定ViewModel的Command

16、DataGrid自动生成列

17、获取icon资源

18、TextBox输入浮点数失败


WPF相关合集如下:

WPF之关于Brush及其多种派生类的定义与使用方式

WPF之关于Command命令的自定义及使用

WPF之关于常用集合控件的定义及使用

WPF之关于依赖属性与附加属性的定义及其使用方式

WPF之关于路由事件与附加事件的自定义及其使用方式

WPF之关于动画Animation的定义、使用方式及其扩展知识

WPF之关于DragDrop拖拽的定义及其多种实现方式

WPF之关于逻辑树与视觉树的遍历及其获取方式

WPF-静态(需重启)与动态(无需重启)切换多语言

一、基础

 了解更多控件介绍请点击:官方文档查询

1、GridSplitter分割线

将分割线加入Grid某行或某列,用户即可通过拖拽改变行或列的尺寸。

 垂直拖拽,示例:


   
        
        
       
   
   
   
   
 

水平拖拽 ,示例:


    
        
        
        
    
    
    
    

2、x:static访问资源文件

 注意:资源文件访问权限须更改为Public

            

WPF-基础及进阶扩展合集(持续更新)_第1张图片


3、wpf触发器

三类型:  属性触发器、数据触发器、事件触发器

使用场景:

        样式:Style.Triggers

        数据模板:DataTemplate.Triggers

        控件模板:ControlTemplate.Triggers

        元素中定义触发器:FrameworkElement.Triggers  //仅支持事件触发器,否则报错

      

4、添加xaml资源文件

pack://application:,,,  可省略 

    
        
            
                
                
            
        
    

5、Convert转换器

①继承IValueConverter接口(Convert方向为Source->Target,ConvertBack反向)实现一个转换器,示例如下:

    public class BoolToColorConvert : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is true) return Brushes.LightBlue;
            else return Brushes.LightGreen;
        }

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

②新建一个转换器资源对象,与Binding绑定,如下:


    
  

6、多路绑定与多路转换器

注意:MultiBinding必须实现转换器

实现IMultiValueConverter接口的多路转换器,示例如下:

    public class MultiConvert : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var high = values[0].ToString();
            if (values[1] is true)
                return $"{high}   true";
            else return $"{high}   false";
        }

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

    


    
         
             
             
         
     


二、进阶扩展

1、HierarchicalDataTemplate

HierarchicalDataTemplate:助层级控件(TreeView、MenuItem)显示层级数据模板

     注意:若结点为同类型(同节点名、同属性名),使用一个Template就行,会自动迭代;

                可通过路由事件方式取出XML数据;

    
        
            
                
                    
                        
                        
                    
                    
                        
                        
                    
                
            
        
        
            
        
        
            
        
        
            
        
    

2、XmlDataProvider从外部文件获取源

 代码如下:

        
            
        
            
                
                    
                        
                            
                                
                                
                                
                            
                        
                    
                
            

3、TextBox在CellTemplate中的焦点问题

当使用GridView作为ListView的View属性时,若某一列使用TextBox作为CellTemplate,那么TextBox获取焦点时目标控件并不会把该项作为SelectedItem

解决方式:通过TextBox的GotFocus事件的事件处理器去追溯到目标控件,获取业务逻辑数据,并将其设置为选中项;

/*********访问业务逻辑数据***************/

TextBox tb=e.OriginalSource as TextBox;//获取事件发起的源头

ContentPresenter cp=tb.TemplateParent as ContentPresenter;//获取模板目标

Student stu=cp.Content as Student;//获取业务逻辑数据

this.listViewStudent.SelectedItem=stu;//设置ListView的选中项

/****************访问界面元素*************************/

ListViewItem lvi=this.listViewStudent.

                itemContainerGenerator.ContainerFromItem(stu) as ListViewItem;//通过条目容器自上而下寻找

CheckBox chb=this.FindVisualChild(lvi);//借助VisualTreeHelper封装的方法

MessageBox.Show(chb.Name);

注意:寻找DataTemplate生成的控件,若结构简单可使用DataTemplate对象的FindName方法,对于结构复杂的控件,只能借助VisualTreeHelper来实现了。 

4、让窗体可裁减

前提:窗体AllowsTransparency属性设为true

                  WindowStyle属性设为None

再使用Clip方法裁剪,指定一个裁剪路径

5_1、获取DataGrid的ScrollViewer

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    _scroll = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.DataGrid, 0), 0) as ScrollViewer;
}

5_2、DataGrid绑定集合改变触发事件

 var itemsource = DataGrid.ItemsSource as ObservableCollection;
 if (itemsource != null)
     itemsource.CollectionChanged += Itemsource_CollectionChanged;

5_3、ScrollViewer自动滚动到尾部

通过ScrollChanged路由事件实现该功能:

private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var scrollViewer = (ScrollViewer)sender;
            // 检查是否已滚动到底部
            bool isAtBottom = scrollViewer.VerticalOffset >= scrollViewer.ScrollableHeight - 1;
            // 如果已滚动到底部,自动滚动到底部
            if (isAtBottom)
            {
                try
                {
                    scrollViewer.ScrollToBottom();
                }
                catch
                {
                    // ignored
                }
            }
        }

6、wpf的Behavior行为

引用System.Windows.Interactivity库

使用事件触发行为

    public class MyBehavior:Behavior

导航:

1、NavigationService.GoBack();  //向下,使用前判断CanGoBack()

2、NavigationService.GoForward();  //向上,使用前判断CanGoForward()

3、NavigationService.Navigate(new Uri("Page3.xaml", UriKind.RelativeOrAbsolute));//导航

使用方法1:

  
       
       BiYin
       
  
 private void Hyperlink_Click(object sender, RoutedEventArgs e)
 {
    Hyperlink hyperlink = (Hyperlink)sender;
    Process.Start(new ProcessStartInfo(hyperlink.NavigateUri.AbsoluteUri));
    //Process.Start(new ProcessStartInfo("https://www.csdn.net/"));
 }

使用2:结合Page使用

                

this.fram.Navigate(new Uri("Page2.xaml", UriKind.RelativeOrAbsolute));

8、Cursor光标属性

FrameworkElement的属性,可设置控件区域光标的不同状态

9、ListView布局、滚动条

1、ItemsPanel:可设置数据项布局水平或垂直

2、ItemContainerStyle :设置每个项的样式,

                                BasedOn:继承指定对象

3、Template:可通过模板给无ScrollViewer功能的容器添加ScrollViewer

                1、ScrollViewer控件:封装了水平、垂直ScrollBar和一个内容容器

                2、ItemsPresenter:itemsControl不负责呈现控件,通过子元素ItemsPresenter负责,放在模板内部,该子元素会检测其父元素是否为集合控件,若是则添至视觉树中
————————————————

更详细点击:
    转到示例

10、DataGrid文本过长换行

通过Column的ElementStyle设置TextBlock的属性如下(注意:Width属性必须设置后才有效)

,该方法会多显示一行,如果太长仍不能显示全部:

            
                
                    
                        
                    
                
            

11、指定字体集FontFamily

①添加字体资源文件;

②双击字体文件可查看字体名称;

③指定字体集;

12、窗体可拖动


        private void Top_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed) DragMove();
        }


13、虚拟化技术提升程序性能

Data Virtualization 通常情况下我们说数据虚拟化是指数据源没有完全加载,仅加载当前需要显示的数据呈现给用户。

UI Virtualization 是针对数据容器渲染数据项的一个优化,WPF中VirtualizingStackPanel容器是实现了UI Virtualization的容器。

VirtualizingPanel.VirtualizationMode="Recycling"表示不循环实例化新的Item,例如Item1--Item20此时可见,拖动滚动条到Item100,再从Item100返回至Item1--Item20时,这时候Item1--Item20不会被重新实例化。默认情况下 VirtualizingPanel.VirtualizationMode="Standard"。

VirtualizingPanel.VirtualizationMode="Recycling" 
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.IsContainerVirtualizable="True"

注意:使用容器虚拟化需设置容器的高度(VirtualizingStackPanel.IsVirtualizing只显示可视部分不是代表我们看到的部分,而是容器能加载的部分。虽然我们可视部分可能只有 Height=680,但是不代表容器只有680高,那么,软件还是会将所有数据加载出来,直到达到容器最大高度。这样虚拟化功能就失效了)

14、查看Binding错误信息

15、DataGrid模板列中Button绑定ViewModel的Command


    
        
            
                
                    

16、DataGrid自动生成列

        private void grid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            var result = e.PropertyName;
            var p = (e.PropertyDescriptor as PropertyDescriptor).ComponentType.GetProperties().FirstOrDefault(x => x.Name == e.PropertyName);
            if (p != null)
            {
                var found = p.GetCustomAttribute();
                if (found != null)
                {
                    result = found.Name;
                    if (found.GetAutoGenerateField() == false)
                    {
                        e.Cancel = true;
                        return;
                    }
                }
                else
                {
                    //根据需求自行更改属性
                    e.Cancel = true;
                    return;
                }
            }

            if (e.Column is DataGridComboBoxColumn)
            {
                var data = ((e.Column as DataGridComboBoxColumn).SelectedItemBinding as Binding);
                data.Mode = BindingMode.TwoWay;
                BindingOperations.SetBinding(e.Column, DataGridColumn.HeaderProperty, LanguageHelper.GetBinding(result));
            }
            else
            {
                var data = ((e.Column as DataGridBoundColumn).Binding as Binding);
                data.Mode = BindingMode.TwoWay;
                BindingOperations.SetBinding(e.Column, DataGridColumn.HeaderProperty, LanguageHelper.GetBinding(result));
            }
        }

        private void CardDataGrid_AutoGeneratedColumns(object sender, EventArgs e)
        {
            foreach (var item in (sender as DataGrid).Columns)
            {
                try
                {
                    if (item is DataGridBoundColumn)
                    {
                        var binding = ((item as DataGridBoundColumn).Binding) as Binding;
                        if (binding != null)
                        {
                            binding.Mode = BindingMode.TwoWay;
                            binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                        }
                    }

                }
                catch (Exception)
                {
                }
            }

        }

17、获取icon资源

推荐阿里矢量图标库:https://www.iconfont.cn/

①添加需要的图标到购物车后,下载代码

②解压后,打开iconfont.js文件,提取Path部分数据

③创建该Path资源,如下:

    M855.552 742.4a40.96 40.96 0 0 1 40.448 41.6c0 22.976-18.112 41.6-40.448 41.6h-282.88a40.96 40.96 0 0 1-40.448-41.6 42.24 42.24 0 0 1 11.84-29.44 39.808 39.808 0 0 1 28.544-12.16h282.944z m-99.84-99.84v282.88a40.96 40.96 0 0 1-41.6 40.448 41.024 41.024 0 0 1-41.6-40.384v-283.008a40.96 40.96 0 0 1 41.6-40.384 42.24 42.24 0 0 1 29.44 11.84c7.744 7.552 12.16 17.856 12.16 28.544zM166.4 928c-21.248 0-38.464-18.88-38.464-42.176 0-209.472 155.008-379.264 346.24-379.264 21.248 0 38.464 18.88 38.464 42.176 0 23.232-17.216 42.112-38.464 42.112-148.736 0-269.312 132.096-269.312 295.04 0 23.232-17.216 42.112-38.4 42.112zM475.52 177.92c-87.552 0-158.528 73.408-158.528 163.904s70.976 163.84 158.528 163.84c87.488 0 158.464-73.344 158.464-163.84 0-90.496-70.976-163.84-158.464-163.84z m0 409.728c-131.328 0-237.76-110.08-237.76-245.824C237.696 206.016 344.128 96 475.52 96c131.2 0 237.696 110.08 237.696 245.824 0 135.744-106.432 245.76-237.696 245.76z
    

或:

var icon = new Path();
icon.Data = ResourceHelper.GetResource("AddAuthrotyGeometry");
icon.SetResourceReference(Shape.FillProperty, "PrimaryTextBrush");
icon.Stretch = Stretch.Uniform;
testMenuItem.Icon = icon;

④使用资源:

  

18、TextBox输入浮点数失败

问题:.net4.5之后,当TextBox绑定触发条件为UpdateSourceTrigger=PropertyChanged时,无法输入小数点,解决方案如下:

方法一:修改Xmal中的StringFormat为StringFormat={}{0},如果StringFormat限定了格式,那么该方法不可用:

方法二:在App.cs的入口函数中加一行代码“FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false”

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;
        base.OnStartup(e);
    }
}

你可能感兴趣的:(WPF基础与进阶,开发语言,wpf)