WPF 和 XAML 的隐藏特性?

这里讨论了各种语言的大量隐藏特性。现在我对 XAML 和 WPF 的一些隐藏特性感到好奇?

我发现的一个事件是 ListView 的头部单击事件

<ListView x:Name='lv'
Height="150"
GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler">

未列出 GridViewColumnHeader. Click 属性。

到目前为止的一些相关特征:

参见:

  1. C # 的隐藏特性
  2. Python 的隐藏特性
  3. Hidden features of ASP.NET
  4. Perl 的隐藏特性
  5. Java 的隐藏特性
  6. VB.NET 的隐藏特性
  7. PHP 的隐藏特性
  8. Hidden features of Ruby
  9. C 语言的隐性特征
  10. 等等... ..。
34099 次浏览

3.5 sp1将 StringFormat 引入到绑定表达式中,例如。

<TextBox Text="{Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}" />

多重绑定 (与 StringFormat 组合) :

<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}, {1}">
<Binding Path="LastName" />
<Binding Path="FirstName" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>

3.5 sp1将 TargetNullValue 引入到绑定中。如果输入了该值,这将把绑定属性设置为 Null,如果属性为 Null,它将显示该值。

<TextBox Text="{Binding Total, TargetNullValue=$0.00}" />

网格大小共享(这是就是一个很好的例子)。长话短说,您可以让网格列和行共享大小,甚至跨越不同的网格。对于所有使用 DataGrid 而不需要在适当的位置编辑数据的人来说,这将是非常宝贵的。

还有 PresentationTraceSource。TraceLevel 调试绑定在任何特定场景中发生的情况的技巧。你要做的就是参考系统。WindowsBase 程序集中的诊断命名空间

xmlns:sd="clr-namespace:System.Diagnostics;assembly=WindowsBase"

然后向绑定表达式添加以下内容:

<TextBlock Text="{Binding Message, sd:PresentationTraceSources.TraceLevel=High}"  />

日志是这样的:

System.Windows.Data Warning: 52 : Created BindingExpression (hash=5923895) for Binding (hash=7588182)
System.Windows.Data Warning: 54 :   Path: 'Message'
System.Windows.Data Warning: 56 : BindingExpression (hash=5923895): Default mode resolved to OneWay
System.Windows.Data Warning: 57 : BindingExpression (hash=5923895): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 58 : BindingExpression (hash=5923895): Attach to System.Windows.Controls.TextBlock.Text (hash=65248697)
System.Windows.Data Warning: 63 : BindingExpression (hash=5923895): Resolving source

这不是一个真正隐藏的功能,但与 WPF/XAML 你得到 Bea StollnitzJosh Smith。皇后和国王的 WPF/XAML 编程。

Advanced "caption" properties

另一件不太清楚的事情是我们习惯于只包含文本的一些属性的内容。如果 GUI 元素的属性是 Object 类型的,那么很可能您不仅可以设置文本,还可以添加一个包含一组控件的需求面板。

An example of this is the MenuItem, where the Header property (which normally just contains text) can contain a set of gui elements wrapped in a panel control (or just one gui element if you need just one).

还要注意 MenuItem 上的 Icon属性。这个属性通常包含一个 Image 元素,但是它也可以包含任何东西!

<MenuItem Name="MyMenuItem" Click="MyMenuItem_Click">
<MenuItem.Icon>
<Button Click="Button1_Click">i</Button>
</MenuItem.Icon>
<MenuItem.Header>
<StackPanel Orientation="Horizontal" >
<Label>My text</Label>
<Button Click="Button2_Click">ClickMe!</Button>
</StackPanel>
</MenuItem.Header>
</MenuItem>

标记扩展和附加属性是我最喜欢的特性,它们使您能够以一种非常优雅的方式扩展 XAML“词汇表”。

标记扩展

<!-- Binding to app settings -->
<CheckBox IsChecked="{my:SettingBinding MinimizeToTray}">Close to tray</CheckBox>


<!-- Fill ItemsControl with the values of an enum -->
<ComboBox ItemsSource="{my:EnumValues sys:DaysOfWeek}"/>


<!-- Localization -->
<TextBlock Text="{my:Localize HelloWorld.Text}"/>


<!-- Switch on the result of a binding -->
<TextBlock Text="{my:Switch Path=IsGood, ValueIfTrue=Good, ValueIfFalse=Bad}"/>

附属财产

<!-- Sort GridView automatically -->
<ListView ItemsSource="{Binding Persons}"
IsSynchronizedWithCurrentItem="True"
util:GridViewSort.AutoSort="True">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Name"
DisplayMemberBinding="{Binding Name}"
util:GridViewSort.PropertyName="Name"/>
<GridViewColumn Header="First name"
DisplayMemberBinding="{Binding FirstName}"
util:GridViewSort.PropertyName="FirstName"/>
<GridViewColumn Header="Date of birth"
DisplayMemberBinding="{Binding DateOfBirth}"
util:GridViewSort.PropertyName="DateOfBirth"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>




<!-- Vista Glass effect -->
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WpfApplication1"
Title="Window1"
my:WinUtil.EnableAeroGlass="True">


...

GridViewsort的源代码(顺便说一下,它使用 Ortus 提到的 GridViewColumnHeader.Click事件)

为窗口添加 Aero 效果

  <Window.Resources>
<ResourceDictionary Source="/PresentationFramework.Aero, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/aero.normalcolor.xaml" />
</Window.Resources>

有时你得到的字符串太长,无法在标签上显示。在这种情况下,我们可以利用 TextBlockTextTrimming属性来显示椭圆

<TextBlock
Name="sampleTextBlock"
TextTrimming="WordEllipsis"
TextWrapping="NoWrap"/>

MSDN Link

在禁用的控件上显示工具提示

Wpf allows to show tooltip on a control, if it is in disabled state.

比如说

<Button Content="Disabled Button" ToolTipService.ShowOnDisabled="True" IsEnabled="False" ToolTip="This is a disabled button"/>

内置型号

If you want to add objects of simple types like string or double to a resource dictionary today you need to map the needed clr-namespaces to an XML namespaces. In XAML 2009 we a lot of simple types that are included in the XAML language.

<!-- XAML 2006 -->
<sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib >Test</sys:String>


<!-- XAML 2009 -->
<x:String>Test</x:String>

XAML 语言包括以下类型:

<x:Object/>
<x:Boolean/>
<x:Char/>
<x:String/>
<x:Decimal/>
<x:Single/>
<x:Double/>
<x:Int16/>
<x:Int32/>
<x:Int64/>
<x:TimeSpan/>
<x:Uri/>
<x:Byte/>
<x:Array/>
<x:List/>
<x:Dictionary/>

Use of Static Factory Methods with x:FactoryMethod

当您有一个没有公共构造函数但有静态工厂方法的类型时,您必须在 XAML2006的代码中创建该类型。使用 XAML2009,您可以使用 x: FactoryMethodx: Arguments 属性来传递参数值。

<!-- XAML 2006 -->
Guid id = Guid.NewGuid();


<!-- XAML 2009 -->
<Guid x:FactoryMethod="Guid.NewGuid" />

支持任意字典键

在 XAML2006中,所有显式的 x: Key 值都被视为字符串。在 XAML2009中,可以通过在 ElementSyntax 中编写键来定义任何类型的键。

<!-- XAML 2006 -->
<StreamGeometry x:Key="CheckGeometry">M 0 0 L 12 8 l 9 12 z</StreamGeometry>


<!-- XAML 2009 -->
<StreamGeometry>M 0 0 L 12 8 l 9 12 z
<x:Key><x:Double>10.0</x:Double></x:Key>
</StreamGeometry>

使用{ x: Reference }的简单对象引用

如果您今天想要创建一个对象引用,您需要执行一个数据绑定并使用 ElementName 声明源。在 XAML2009中,可以使用新的{ x: Reference }标记扩展

<!-- XAML 2006 -->
<Label Target="{Binding ElementName=firstName}">FirstName</Label>
<TextBox x:Name="firstName" />


<!-- XAML 2009 -->
<Label Target="{x:Reference firstName}">FirstName</Label>
<TextBox x:Name="firstName" />

与 x: 参数一起使用非默认构造函数

在 XAML 2006中,对象必须具有使用它们的公共缺省构造函数。在 XAML2009中,可以使用 x: Arguments 语法传递构造函数参数。

<!-- XAML 2006 -->
<DateTime>00:00:00.0000100</DateTime>


<!-- XAML 2009 -->
<DateTime>
<x:Arguments>
<x:Int64>100</x:Int64>
</x:Arguments>
</DateTime>

XAML 中带有 x: TypeArguments 的泛型

如果希望在 XAML 中使用 Observer ableCollection,则需要创建一个派生自 Observer ableCollection 的类型,因为无法在 XAML 中声明它。使用 XAML2009,您可以使用 x: TypeArguments 属性来定义泛型类型的类型。

<!-- XAML 2006 -->
class EmployeeCollection : ObservableCollection<Employee>
{
}


<l:EmployeeCollection>
<l:Employee FirstName="John" Name="Doe" />
<l:Employee FirstName="Tim" Name="Smith" />
</lEmployeeCollection>


<!-- XAML 2009 -->
<ObservableCollection x:TypeArguments="Employee">
<l:Employee FirstName="John" Name="Doe" />
<l:Employee FirstName="Tim" Name="Smith" />
</ObservableCollection />

按代码设置 ValidationError

A ValidatioRule in a BindingExpression only triggers, when the target side of the binding changes. If you want to set a validation error by code you can use the following snippet.

设置验证错误

ValidationError validationError =
new ValidationError(regexValidationRule,
textBox.GetBindingExpression(TextBox.TextProperty));


validationError.ErrorContent = "This is not a valid e-mail address";


Validation.MarkInvalid(
textBox.GetBindingExpression(TextBox.TextProperty),
validationError);

清除验证错误

Validation.ClearInvalid(textBox.GetBindingExpression(TextBox.TextProperty));

调试动画

常见错误

如果您得到以下错误: 无法动画’(0)。(1)在不可变物件的情况下。你可能会遇到以下限制之一:

  • 您正在使依赖项属性具有动画效果,而不设置本地值
  • 您正在动画一个依赖项属性,该属性的当前值是在另一个未合并到资源字典中的程序集中定义的。
  • You are animating a value that is currently databound

PriorityBinding 允许您按照“先来先看”的顺序使用 asyn 绑定:

<TextBlock.Text>
<PriorityBinding FallbackValue="defaultvalue">
<Binding Path="SlowestDP" IsAsync="True"/>
<Binding Path="SlowerDP" IsAsync="True"/>
<Binding Path="FastDP" />
</PriorityBinding>
</TextBlock.Text>

系统颜色用法

<Border Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>

您可以使用加号(+)来引用 XAML 中的嵌套类型:

public class SomeClass
{
public enum SomeEnum
{
SomeValue
};
}

我们可以使用以下语法在 XAML 中引用 SomeValue:

{x:Static local:SomeClass+SomeEnum.SomeValue}

这种语法是 没有在 MSDN 上记录,并且不受官方支持。有人在 MSDN 论坛 问了一下,显然它破坏了 VS2010的 WPF 设计器。它在微软连接上有 被报告了

将 UIElement (s)填充到 TextBlock 中的能力

我不知道这有多大用处(虽然它算是隐藏的) ... ... 但当我 第一次遇到它的时候,它确实让我措手不及:

<Grid x:Name="LayoutRoot">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid>
<Rectangle Fill="AliceBlue" Width="25" Height="25"/>
</Grid>
</TextBlock>
</Grid>

你可以认为下面的 xaml 是有用的(例如,在某些文本的末尾放置一个图形) :

<Grid>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Hello World">
<TextBlock.Resources>
<DrawingBrush x:Key="exclamationPoint" Stretch="Uniform">
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Brush="#FF375CE2" Geometry="F1 M 7.968,58.164L 0,58.164L 1.914,49.921L 9.882,49.921L 7.968,58.164 Z M 21.796,0L 11.054,42.148L 4.403,42.148L 13.049,0L 21.796,0 Z "/>
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</TextBlock.Resources>
<Grid>
<Rectangle Width="100" Height="100" Fill="{StaticResource exclamationPoint}"/>
</Grid>
</TextBlock>
</Grid>

上面的 xaml 呈现如下:

Hello World

不带 INotifyPropertyChanged 或 DependencyProperties 的绑定

如前所述,可以在不使用 INotifyPropertyChanged 的情况下绑定纯 CLR 对象属性,而且它将使用 工作而已

这里是 论坛邮报我指的是。

语录:

[ ... ] WPF 的数据绑定引擎将数据绑定到 PropertyDescriptor 实例,如果源对象是一个普通的 CLR 对象并且没有实现 INotifyPropertyChanged 接口,该实例将包装源属性。数据绑定引擎将尝试通过 PropertyDescriptor 订阅属性更改事件。AddValueChanged ()方法。当目标数据绑定元素更改属性值时,数据绑定引擎将调用 PropertyDescriptor。SetValue ()方法将更改后的值传输回源属性,并且它将同时引发 ValueChanged 事件以通知其他订阅者(在本例中,其他订阅者将是 ListBox 中的 TextBlock)。

如果您正在实现 INotifyPropertyChanged,则完全有责任在需要绑定到 UI 的属性的每个设置器中实现更改通知。否则,更改将不会像您期望的那样同步。[...]

Here is another 伟大而详细的文章 on the subject.

注意 this only works when using binding。如果更新值 来自代码,则更改 不会被通知的。[ ... ]

实现 INotifyPropertyChanged 可能是一项相当繁琐的开发工作。但是,您需要将这项工作与 WPF 应用程序的运行时占用(内存和 CPU)进行权衡。自己实现 INPC 将节省运行时 CPU 和内存.