WPF和XAML的隐藏功能?


123

这是为各种语言讨论的大量隐藏功能。现在,我对XAML和WPF的某些隐藏功能感到好奇吗?

我发现的一个是ListView的标题单击事件

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

GridViewColumnHeader.Click属性未列出。

到目前为止的一些相关功能:

也可以看看:

  1. C#的隐藏功能
  2. Python的隐藏功能
  3. ASP.NET的隐藏功能
  4. Perl的隐藏功能
  5. Java的隐藏功能
  6. VB.NET的隐藏功能
  7. PHP的隐藏功能
  8. Ruby的隐藏功能
  9. C的隐藏功能
  10. 等等........

7
在此处查看msdn.microsoft.com/en-us/library/…。click事件是从ButtonBase继承的。您所描述的是附加事件,这是WPF中一个非常强大的概念(msdn.microsoft.com/zh-cn/library/bb613550.aspx)。这样,您可以在网格上有100个按钮且只有1个处理程序的<Grid Button.Click>。
Sorskoot

1
起初我就像“哦,我们再来一次”,但是后来我在响应中学到了一些东西,所以我全都收回了::o –o
Sam Harwell

1
应该是社区Wiki
tsilb

2
@tsilb我不认为它应该是社会的维基,有看看这个链接meta.stackexchange.com/questions/392/...
PRASHANT Cholachagudda

Answers:


87

多重绑定(与StringFormat结合使用):

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

1
很棒:-),除非您使用的是Silverlight 4或更早版本。v5手指交叉
Simon_Weaver

5
这很棒,但是我很想不这样做。如果我需要构建一个字符串,我会将其作为逻辑进行分类,并希望对输出进行单元测试。在视图模型中,有时将这样的东西作为string.Format()更好。
伊恩·霍尔德

58

还有PresentationTraceSources.TraceLevel技巧可以调试任何特定情况下绑定的情况。您所要做的就是在WindowsBase程序集中引用System.Diagnostics命名空间

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 

4
在Visual Studio 2010中,您需要将跟踪设置的级别设置为警告!见stackoverflow.com/questions/2802662/...
WaltiD

44

3.5sp1将TargetNullValue引入了绑定。如果输入值,这会将绑定属性设置为Null;如果您的属性为Null,它将显示此值。

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

44

3.5sp1将StringFormat引入了绑定表达式,例如

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

我无法说出我有多喜欢这个功能。我讨厌有成堆的价值转换器。
罗布

是的,很容易添加的最省时的功能之一。特别是当与TargetNullValue结合使用时,很多问题都会消失。
布赖恩·安德森

6
在StringFormat周围加上单引号应删除一些编译器警告Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"
Ryan Versaw 09年

很高兴知道,我已经习惯了无视它们。
布赖恩·安德森

1
我试图传达任何任意格式的字符串都可以工作。我认为在这种情况下,国际化版本为StringFormat ='{} {0:d}'。
布莱恩·安德森


27

向窗口添加航空效果

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

1
添加了代码,但仍未添加Aero效果。我想念什么吗?
Elmo 2012年

21

XAML中带有x:TypeArguments的泛型

如果要在XAML中使用ObservableCollection,则需要创建一个从ObservableCollection派生的类型,因为您不能在XAML中声明它。在XAML 2009中,可以使用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 />

1
不幸的是,x:TypeArguments仅在宽松的xaml文件中可用,而在未编译的文件中不可用:(
kevindaub 2011年

是的,松散XAML只:(对于大多数WPF开发XAML2009也没用。
格里戈里·

19

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

如果控件处于禁用状态,则Wpf允许在控件上显示工具提示。

例如

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

19

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

在XAML 2006中,对象必须具有公共默认构造函数才能使用它们。在XAML 2009中,可以使用x:Arguments语法传递构造函数参数。

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

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


18

标记扩展和附加属性是我最喜欢的功能,它们使您能够以非常优雅的方式扩展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的源代码(顺便说一句,它使用GridViewColumnHeader.ClickOrtus提到的事件)


WinUtil.EnableAeroGlass可在某处找到源吗?
奥斯卡(Oskar)2010年

是的,但是自从我发布此内容以来,它已经发生了很大变化。现在有2个属性,EnableBlur和GlassFrameMargins。:你可以在这里找到的代码projets.developpez.com/projects/dvp-net/repository/entry/trunk/...
托马斯Levesque的

15

您可以使用加号(+)引用XAML中的嵌套类型。例如,如果我们有此类:

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

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

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

MSDN上未记录此语法,并且未正式支持该语法。有人在MSDN论坛上询问了它,显然它破坏了VS2010的WPF设计器。它已被报道微软连接。


14

网格大小共享(这是一个很好的示例)。长话短说,即使跨不同的网格,您也可以使网格的列和行共享大小。对于所有需要使用DataGrid而不需要就地编辑数据的人来说,这都是无价的。



10

通过x:FactoryMethod使用静态工厂方法

当您的类型没有公共构造函数而是静态工厂方法时,必须在XAML 2006中的代码中创建该类型。对于XAML 2009,您可以使用x:FactoryMethodx:Arguments属性来传递参数值。

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

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

7

先进的“字幕”属性

另一个不太清楚的是,我们习惯于仅包含文本的某些属性的内容。如果GUI元素的属性为Object类型,则很有可能您可以添加一个包含一组控件的面板,而不仅仅是设置文本。

例如MenuItem,其中的Header属性(通常只包含文本)可以包含包装在面板控件中的gui元素集(如果只需要一个gui元素)。

还要注意IconMenuItem上的属性。通常包含一个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>

7

也非常有用:GridLengthConverter,BooleanToVisibilityConverter,AlternationConverter全部位于System.Windows.Controls中
MaciekŚwiszczowski2011年

6

内置类型

如果今天要向资源字典中添加简单类型的对象(例如字符串或双精度型),则需要将所需的clr-namespaces映射到XML名称空间。在XAML 2009中,我们在XAML语言中包含了许多简单的类型。

<!-- 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/> 

如果使用WPF处理XAML,这将不起作用。msdn.microsoft.com/en-us/library/ee792007.aspx
scobi 2010年

6

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

如果今天要创建对象引用,则需要进行数据绑定并使用ElementName声明源。在XAML 2009中,您可以使用新的{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:Reference是XAML 2009语言功能,但在某些情况下它也可以在已编译的XAML中工作。但是,它并非在所有地方都有效,并且可能会破坏XAML设计器视图。
Mike Strobel

1
@MikeStrobel:它几乎可以在任何地方工作,而且我也不会不在乎设计师的突破。
HB

6

系统颜色用法

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

3
将其指定为DynamicResource很重要,因为用户可以在应用程序运行时更改系统颜色。
M. Dudley

3

支持任意字典键

在XAML 2006中,所有显式x:Key值均视为字符串。在XAML 2009中,可以通过在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>

2

通过代码设置ValidationError

仅在绑定的目标端发生更改时,才会触发BindingExpression中的ValidatioRule。如果要通过代码设置验证错误,可以使用以下代码段。

设置验证错误

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));

2

将UIElement塞入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呈现如下:

你好,世界


1

调试动画

常见错误

如果出现以下错误:无法为不可变对象实例设置'(0)。(1)'的动画。您可能会遇到以下限制之一:

  • 您正在为依赖项属性设置动画而不设置本地值
  • 您正在为一个依赖项属性设置动画,该依赖项属性的当前值是在另一个未合并到资源字典中的程序集中定义的。
  • 您正在为当前数据绑定的值设置动画

1

没有INotifyPropertyChanged或DependencyProperties的绑定

如此处所讨论的您可以绑定一个普通的CLR对象属性而无需INotifyPropertyChanged,它将正常工作

这是我指的Forumpost

引用:

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

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

这是关于该主题的另一篇很棒且详细的文章

请注意,这仅在使用binding时有效。如果从代码更新值,则更改不会被通知。[...]

实现INotifyPropertyChanged可能是相当繁琐的开发工作。但是,您需要根据WPF应用程序的运行时占用空间(内存和CPU)权衡该工作。自己实施INPC将节省运行时的CPU和内存

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.