WPF 注意的小知识点

xiaoxiao2025-05-16  35

1、TextOptions.TextFormattingMode="Display"的目的是为了解决WPF中文字体显示模糊的问题。

2、通过storyboard动画修改控件属性后,在通过别的方式(除了storydboard外)没别的方式了,现在有3种方式解决这个问题:

方法一:将动画的 FillBehavior 属性设置为 Stop: storyboard.FillBehavior = FillBehavior.Stop; 通过将FillBehavior设置为Stop,即通知动画在到达其活动期末尾后停止影响其目标关联属性。虽然达到了目的,但必须等待动画结束时才会生效,且更关键的是之前被storyboard修改过的所有关联属性值此时都被还原成了初始值。因此,此方法只适合用于制作类似网页中的导航菜单按钮:当鼠标悬停在菜单上时,菜单图形按钮执行一段华丽的变化动画;当鼠标移开后即变回为初始图片。

方法二:移除整个动画板(Storyboard)。此方法必须通过类似            Leader.BeginStoryboard(storyboard, HandoffBehavior.SnapshotAndReplace, true);或 storyboard.Begin(Leader, HandoffBehavior.SnapshotAndReplace, true); 这两种方式启动动画,然后在需要解锁时通过 storyboard.Remove(Leader); storyboard = null; 通知动画板动画停止影响名为Leader对象的目标关联属性,并移除storyboard。需要特别注意的是①必须将动画的IsControllable参数设置为true;②HandoffBehavior最好设置为SnapshotAndReplace,此枚举的作用是:新动画将替换它们所应用到的关联属性上的任何现有动画。

方法三:从单个关联属性移除动画。同样的以精灵角色朝向为例,如果该属性已被Storyboard锁定,那么如果此时需要对其值进行更改,我们可以通过类似: Leader.BeginAnimation(QXSpirit.DirectionProperty, null);或 Leader.ApplyAnimationClock(QXSpirit.DirectionProperty, null); 这两种方法来禁止关联到Leader的动画继续影响Leader的DirectionProperty关联属性(此方法对于非动画板动画也同样有效)。接着后面我们就可以轻松的通过Leader.Direction = 0 为精灵的朝向属性进行赋值并在画面中得到体现。     以上三种解决方案在WPF中灵活的配合storyboard.Children.Clear();使用几乎可以应付任何关于Storyboard锁死关联属性的问题;但是在Silverlight中却往往不尽如人意。毕竟只是WPF的子集,在功能与方法上有着太少的支持。因此,我拓展了以下两种解决方案,更重要的,它们均为WPF/Silverlight通用的且药到病除的终极策略。

方法四:可以通过每次运行新的动画时先暂停之前的动画(注意,是暂停(Pause)而不是停止(Stop)),例如storyboard.Pause(Leader);然后再创建一个新的动画板storyboard = new Storyboard();这样,之前被storyboard修改过的关联属性目标值会被新的storyboard作为起点属性值,从而完美实现关联属性在动画与动画之间的衔接。有些朋友会问那之前的storyboard是否会继续占用内存空间?对于.net的内存回收机制我们无法控知,根据我多方查阅的资料,若您不放心,不妨在创建新的Storyboard前,通过storyboard = null 将之注销掉,在Silverlight动画中我是这样做的,实践证明此方法确实达到的目的。

方法五:以毒攻毒。既然是Storyboard锁死了我们需要更改的关联属性,那么我们同样可以通过Storyboard动画的形式来赋值更改这些关联属性。此方法乃下下策,缺点是毫无性能而言;优点是万能性:适合一切被Storyboard锁死的关联属性的修改,且无论是在WPF还是Silverlight中。下面同样以精灵的朝向为例,我们可以通过: DoubleAnimation doubleAnimation = new DoubleAnimation(); doubleAnimation.To = direction; doubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(10)); Storyboard.SetTarget(doubleAnimation, spirit); Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("Direction")); storyboard.Children.Add(doubleAnimation); storyboard.Begin(); 这样的动画形式对QXSpirit.DirectionProperty关联属性进行强行更改。       本节小结:希望以上5种解锁Storyboard关联属性的解决方案能对大家的WPF/Silverlight动画开发有所帮助;同时,如果哪些地方有写得不妥或有错漏的也请大家不吝赐教,我会及时进行修改及更正。

3、WPF ScrollViewer嵌套Listbox无法滚动

最近在做项目的时候,发现listBoxzi自带的垂直滚动条有问题,经常在Add(item)的时候下面会多出一些空白的部分,而且滚动条的长度也是无规则的,一会大一会小,索性就直接在listBox外面包裹一个ScrollViewer。  ScrollViewer中放一个listBox,可以拖动滚动条,但是滚轮上下滚动无效,后来查阅了资料找到原因,是因为listBox中自带一个滚动条,滚轮上下滚动事件应该是被截获了,而并没有传递到ScrollViewer这一层导致的,那么怎么解决呢?  很简单,直接让listBox.Enable=false或者listBox.IsHitTextVisable=false即可,但是这样有个缺点,就是无法选择listBox中的内容了,那只能用另一个方法,代码如下:

      ListBox.PreviewMouseWheel += (sender, e) =>            {                var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);                eventArg.RoutedEvent = UIElement.MouseWheelEvent;                eventArg.Source = sender;                ListBox.RaiseEvent(eventArg);            };

将listBox的滚动时间传递到上层,让ScrollViewer去处理即可.

4、虚拟化:

如果当前控件更改控件模板后,开启虚拟化需要启动3个属性。如:

VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" ScrollViewer.CanContentScroll="True"

如果是listbox控件,运用分组样式后开启虚拟化需要多添加一个属性VirtualizingPanel.IsVirtualizingWhenGrouping="True"。

5、调用winmm.dll进行录音时,保存的文件路径中不能有“-”;

6、a、treeview控件加载大量数据时,采用分页的形式显示;

  例如:先加载当前页面中能显示的数量,当滚动条滚动到最后时在加载同样数量的数据;

     b、wpf的treeview,如果mvvm中设置了isselected为true的时候,如果前台对应的item没有显示,即没有获得焦点,是不会触发selected事件的

7、WPF 简单的内存优化 

WPF的内存问题困扰了很久. 众所周知,如果长时间使用WPF的程序,它的内存占有将会持续增长。甚至持续的点击一个Button,它的内存也会不断的增长。这是我觉得WPF唯一不够尽人意的地方吧。 那么,难道就没有改善WPF内存的方法吗? 在网上搜索了很久,终于找到了一个比较可行的办法。 首先,感谢网友的分享: http://www.dotnetdev.cn/2010/04/wpf内存释放解决方案/ 这个方法的意思是当程序处于闲置状态时(即改程序处于未激活状态),那么我们可以通过kernel32.dll将物理内存与虚拟内存进行交换。即将主内存的资源暂时放到虚拟内存中。这样就减轻了物理内存的负担。 MSDN对这个函数的解释: 使用这个函数来设置应用程序最小和最大的运行空间,只会保留需要的内存。当应用程序被闲置或系统内存太低时,操作系统会自动调用这个机制来设置应用程序的内存。应用程序也可以使用 VirtualLock 来锁住一定范围的内存不被系统释放。 当你加大运行空间给应用程序,你能够得到的物理内存取决于系统,这会造成其他应用程序降低性能或系统总体降低性能,这也可能导致请求物理内存的操作失败,例如:建立 进程,线程,内核池,就必须小心的使用该函数。 实际上,这个函数并不能真正的释放内存,而只是重新分配改程序的内存占用,将暂时不需要的内容放进虚拟内存,当应用程序重新激活时,会将虚拟内存的内容重新加载到内存。所以,我们不宜过度频繁的调用该方法,这样只会使性能变低。 实际使用中,我们只需要当窗口关闭时,或者最小化时调用此方法即可解决内存不能释放的问题,该方法同样适用于Silverlight和Winform。         [DllImport("kernel32.dll")] public static extern int SetProcessWorkingSetSize(IntPtr proc, int min, int max);         protected override void OnDeactivated(EventArgs e)         {             base.OnDeactivated(e);             SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);         }   补充:后来发现也可以通过限制程序的使用内存进行优化。但是这需要知晓程序的最大内存占有。         int maxWorkingSet = 1024000;         public static void SetWorkingSet(int maxWorkingSet)         {             IntPtr min = System.Diagnostics.Process.GetCurrentProcess().MinWorkingSet;             try             {                 System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet = (IntPtr)maxWorkingSet;             }             catch ()             {                 System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet = min;             }         }  private void Window_Deactivated(object sender, EventArgs e)         {             try             {                 SetWorkingSet(maxWorkingSet);             }             catch ()             {             }         }

8、WPF xmal标记扩展(MarkupExtension)

为实现标记扩展,我们还需要实现MarkupExtension类的ProvideValue方法。

9、ObservableCollection集合加载大量数据时很慢,而且大量数据清理时也很慢;

   加载大量数据时,集合尽量用List集合,性能比较稳定且速度快;

10、列表测试数据快速生成 

   Enumerable.Range(0, 100).Select(i => new { Id = i, Name = "Name - " + i });

11、后台设置宽度为 * 号

   DataGridLength length=new DataGridLength(1,DataGridLengthUnitType.Star);    lastColumn.Width = length;

12、Slider高亮一段区域 SelectionStart="10"  SelectionEnd="40" Minimum="0" Maximum="100" Value="50"  IsSelectionRangeEnabled="True"

13、Color color = new Color();             //设置为红色             color = Color.FromRgb(255, 0, 0);             //设置为半透明的红色             color = Color.FromArgb(100, 255, 0, 0);             //通过字符串方式为颜色赋值,字符串格式为"#aarrggbb".前两位为透明度A,后面依次为R,G,B,并且需要十六进制数值表示             color = (Color)ColorConverter.ConvertFromString("#FFFF0000");

14、WPF的按钮,默认没有MouseDown和MouseUp,需要自己手动加

  r1.AddHandler(Button.MouseDownEvent, new RoutedEventHandler(r1_MouseDown), true);                              r1.AddHandler(Button.MouseUpEvent, new RoutedEventHandler(r1_MouseUp), true);

15、当原控件的某个属性有问题满足不了需求,属性重写

      static AyTextBox()         {             DefaultStyleKeyProperty.OverrideMetadata(typeof(AyTextBox), new FrameworkPropertyMetadata(typeof(AyTextBox)));

            TextProperty.OverrideMetadata(                 typeof(AyTextBox),                 new FrameworkPropertyMetadata(new PropertyChangedCallback(TextPropertyChanged)));         }

16、 [前台方式]对于前台演示demo  需要反射枚举,你可以这样做

引入   xmlns:system="clr-namespace:System;assembly=mscorlib"    

ObjectDataProvider x:Key="placementEnum" MethodName="GetValues" ObjectType="{x:Type System:Enum}">             <ObjectDataProvider.MethodParameters>                 <x:Type TypeName="PlacementMode"/>             </ObjectDataProvider.MethodParameters>         </ObjectDataProvider>

<ComboBox x:Name="placementSelector" ItemsSource="{Binding Source={StaticResource placementEnum}}" IsSynchronizedWithCurrentItem="True" Width="100"  SelectedIndex="2" HorizontalAlignment="Left"/>

17、自定义控件 ,标记某些style只能用于某个类型 [StyleTypedPropertyAttribute(Property = "ItemContainerStyle", StyleTargetType = typeof(ListViewItem))] public class ListView : ListBox

18、附加 事件后台代码

 public AyTreeView()         {             this.AddHandler(TreeViewItem.ExpandedEvent, new RoutedEventHandler(AyTreeViewItemExpanded));          }

        private void AyTreeViewItemExpanded(object sender, RoutedEventArgs e)         {             TreeViewItem tvi = e.OriginalSource as TreeViewItem;             if (tvi != null)             {                 AyMessageBox.ShowInformation(string.Format("TreeNode '{0}' was expanded", tvi.Header));             }         }

19、获得句柄 窗体:  IntPtr hwnd = new WindowInteropHelper(this).Handle;

控件:  IntPtr hwnd = ((HwndSource)PresentationSource.FromVisual(uielement)).Handle;

转载请注明原文地址: https://www.6miu.com/read-5030192.html

最新回复(0)