Versteckte Funktionen von WPF und XAML?

123

Hier finden Sie eine große Anzahl versteckter Funktionen, die für verschiedene Sprachen erläutert werden. Jetzt bin ich neugierig auf einige versteckte Funktionen von XAML und WPF?

Eines, das ich gefunden habe, ist das Header-Klick-Ereignis einer ListView

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

Die GridViewColumnHeader.Click-Eigenschaft ist nicht aufgeführt.

Einige der bisher relevanten Funktionen:

Siehe auch:

  1. Versteckte Funktionen von C #
  2. Versteckte Funktionen von Python
  3. Versteckte Funktionen von ASP.NET
  4. Versteckte Funktionen von Perl
  5. Versteckte Funktionen von Java
  6. Versteckte Funktionen von VB.NET
  7. Versteckte Funktionen von PHP
  8. Versteckte Funktionen von Ruby
  9. Versteckte Funktionen von C.
  10. Und so weiter........
Sauron
quelle
7
Schauen Sie hier msdn.microsoft.com/en-us/library/… . Das Klickereignis wird von ButtonBase geerbt. Was Sie beschreiben, sind angehängte Ereignisse, ein ziemlich leistungsfähiges Konzept in WPF ( msdn.microsoft.com/en-us/library/bb613550.aspx ). Auf diese Weise können Sie <Grid Button.Click> mit 100 Schaltflächen in einem Raster und nur 1 Handler ausführen.
Sorskoot
1
Zuerst sagte ich: "Oh, jetzt geht es wieder los", aber dann habe ich etwas in den Antworten gelernt, also nehme ich alles zurück: o: o
Sam Harwell
1
sollte Community-Wiki sein
Tsilb
2
@tsilb Ich denke nicht, dass es Community-Wiki sein sollte, schauen Sie sich diesen Link meta.stackexchange.com/questions/392/…
Prashant Cholachagudda

Antworten:

87

Multibinding (kombiniert mit StringFormat):

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat="{}{0}, {1}">
      <Binding Path="LastName" />
      <Binding Path="FirstName" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>
Julien Poulin
quelle
1
genial :-) es sei denn du verwendest silverlight 4 oder früher. Daumen
drücken
5
Das ist großartig, aber ich wäre versucht, es NICHT zu tun. Wenn ich einen String erstellen muss, würde ich das als Logik klassifizieren und die Ausgabe einem Unit-Test unterziehen. Solche Dinge sind im Ansichtsmodell manchmal besser als Zeichenfolge.Format ().
Iain Holder
58

Es gibt auch den PresentationTraceSources.TraceLevel-Trick, um zu debuggen, was mit Bindungen in einem bestimmten Szenario passiert. Sie müssen lediglich auf den System.Diagnostics-Namespace in der WindowsBase-Assembly verweisen

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

und fügen Sie dann dem Bindungsausdruck Folgendes hinzu:

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

Das Protokoll sieht folgendermaßen aus:

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 
idursun
quelle
4
In VisualStudio 2010 müssen Sie die Ebene der Traceeinstellungen auf Warnung setzen! Siehe stackoverflow.com/questions/2802662/…
WaltiD
44

3.5sp1 führte TargetNullValue in Bindungen ein. Dadurch wird die gebundene Eigenschaft auf Null gesetzt, wenn der Wert eingegeben wird. Wenn Ihre Eigenschaft Null ist, wird dieser Wert angezeigt.

<TextBox Text="{Binding Total, TargetNullValue=$0.00}" />
Bryan Anderson
quelle
44

3.5sp1 führte StringFormat in Bindungsausdrücke ein, z

<TextBox Text="{Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}" />
Bryan Anderson
quelle
Ich kann nicht in Worte fassen, wie sehr ich diese Funktion liebe. Ich hasste es, Tonnen von Wertumwandlern herumliegen zu haben.
Rob
Ja, einfach eine der zeitsparendsten Funktionen hinzugefügt. Insbesondere in Kombination mit TargetNullValue verschwinden viele Probleme.
Bryan Anderson
6
Wenn Sie das StringFormat in einfache Anführungszeichen setzen, sollten einige Compiler-Warnungen entfernt werden -Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"
Ryan Versaw
Gut zu wissen, ich habe mich daran gewöhnt, sie einfach zu ignorieren.
Bryan Anderson
1
Ich habe versucht zu vermitteln, dass jede beliebige Formatierungszeichenfolge funktioniert. Ich glaube, die internationalisierte Version wäre in diesem Fall StringFormat = '{} {0: d}'.
Bryan Anderson
29

Manchmal erhalten Sie eine Zeichenfolge, die zu lang ist, um auf dem Etikett angezeigt zu werden. In diesem Fall können wir die TextTrimmingEigenschaft von verwenden TextBlock, um Ellipsen anzuzeigen

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

MSDN Link

Prashant
quelle
Erwägen
Sie
27

Hinzufügen eines Aero-Effekts zum Fenster

  <Window.Resources>
    <ResourceDictionary Source="/PresentationFramework.Aero, Version=3.0.0.0, Culture=neutral, 
        PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/aero.normalcolor.xaml" />
</Window.Resources>
Sauron
quelle
1
Der Code wurde hinzugefügt, aber der Aero-Effekt wird immer noch nicht hinzugefügt. Vermisse ich etwas
Elmo
21

Generika in XAML mit x: TypeArguments

Wenn Sie eine ObservableCollection in XAML verwenden möchten, müssen Sie einen Typ erstellen, der von ObservableCollection abgeleitet ist, da Sie ihn in XAML nicht deklarieren können. Mit XAML 2009 können Sie das Attribut x: TypeArguments verwenden, um den Typ eines generischen Typs zu definieren.

<!-- 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 />
Sauron
quelle
1
Leider ist x: TypeArguments nur in losen xaml-Dateien verfügbar und nicht in kompilierten :(
kevindaub
Ja, nur lose XAML :( Für die Mehrheit der WPF-Entwickler ist XAML2009 nutzlos.
Grigory
19

Tooltip auf einem deaktivierten Steuerelement anzeigen

Mit Wpf kann der Tooltip für ein Steuerelement angezeigt werden, wenn es deaktiviert ist.

Beispielsweise

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

Verwendung von Nicht-Standardkonstruktoren mit x: Argumenten

In XAML 2006 müssen Objekte über einen öffentlichen Standardkonstruktor verfügen, um sie verwenden zu können. In XAML 2009 können Sie Konstruktorargumente mithilfe der Syntax x: Arguments übergeben.

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

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

Nicht wirklich eine versteckte Funktion, aber mit WPF / XAML erhalten Sie Bea Stollnitz und Josh Smith . Königin und König der WPF / XAML-Programmierung.

Bryan Anderson
quelle
3
Was ist Karl? Der Jack? Oder der Joker?
Plots
18

Markup-Erweiterungen und angehängte Eigenschaften sind meine Lieblingsfunktionen. Sie ermöglichen es Ihnen, das "Vokabular" von XAML auf sehr elegante Weise zu erweitern.

Markup-Erweiterungen

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

Angehängte Eigenschaften

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

...

Quelle für GridViewSort (übrigens verwendet es das GridViewColumnHeader.Clickvon Ortus erwähnte Ereignis)

Thomas Levesque
quelle
Ist die Quelle für WinUtil.EnableAeroGlassirgendwo verfügbar?
Oskar
Ja, aber es hat sich sehr geändert, seit ich dies gepostet habe ... Es gibt jetzt 2 Eigenschaften, EnableBlur und GlassFrameMargins. Den Code finden Sie hier: projets.developpez.com/projects/dvp-net/repository/entry/trunk/…
Thomas Levesque
15

Sie können mit dem Pluszeichen ( +) auf verschachtelte Typen in XAML verweisen . Wenn wir zum Beispiel diese Klasse hätten:

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

Wir könnten SomeValuein XAML mit der folgenden Syntax verweisen :

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

Diese Syntax ist in MSDN nicht dokumentiert und wird nicht offiziell unterstützt. Jemand hat in den MSDN-Foren danach gefragt , und anscheinend bricht es den WPF-Designer von VS2010. Es ist berichtet worden , auf Microsoft Connect.

M. Dudley
quelle
14

Teilen der Rastergröße ( hier ein gutes Beispiel). Kurz gesagt, Sie können Rasterspalten und -zeilen auch über verschiedene Raster hinweg gemeinsam nutzen. Dies ist von unschätzbarem Wert für alle Personen, die DataGrids verwenden, ohne die vorhandenen Daten bearbeiten zu müssen.

Bryan Anderson
quelle
11

PriorityBinding . Ermöglicht die Verwendung von Asyn-Bindungen in der Reihenfolge "Wer zuerst kommt, mahlt zuerst":

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

Verwendung statischer Factory-Methoden mit x: FactoryMethod

Wenn Sie einen Typ haben, der keinen öffentlichen Konstruktor, sondern eine statische Factory-Methode hat, mussten Sie diesen Typ in XAML 2006 im Code erstellen. Mit XAML 2009 können Sie das Attribut x: FactoryMethodx: Arguments verwenden, um die Argumentwerte zu übergeben.

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

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

Erweiterte "Beschriftung" -Eigenschaften

Eine andere Sache, die nicht sehr klar ist, ist der Inhalt einiger Eigenschaften, die wir gewohnt sind, nur Text zu enthalten. Wenn die Eigenschaft eines GUI-Elements vom Typ Objekt ist, können Sie sehr wahrscheinlich, anstatt nur den Text festzulegen, ein Bedienfeld hinzufügen, das eine Reihe von Steuerelementen enthält.

Ein Beispiel hierfür ist das MenuItem, bei dem die HeaderEigenschaft (die normalerweise nur Text enthält) eine Reihe von GUI-Elementen enthalten kann, die in ein Bedienfeld eingeschlossen sind (oder nur ein GUI-Element, wenn Sie nur eines benötigen).

Beachten Sie auch die IconEigenschaft im MenuItem. Dies enthält normalerweise ein Image-Element, kann aber auch alles enthalten!

<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>
Ehrfurcht
quelle
7

XAML-Konverter

Die folgende Liste zeigt Konverter, die von der WPF-Community entwickelt wurden, um verschiedene Formate in XAML zu konvertieren oder umgekehrt.

Adobe Illustrator XAML-Export-Plugin

Adobe Photoshop zu XAML Converter

Blender XAML Export Plugin

Lightwave XAML Export Plugin

Visio XAML Export

3D Studio Max zu XAML Konverter

Maya zu XAML Konverter

Flash to XAML Converter

SVG zu XAML Konverter

WMF / EMF zu XAML Konverter

Sauron
quelle
auch sehr nützlich: GridLengthConverter, BooleanToVisibilityConverter, AlternationConverter alle in System.Windows.Controls
Maciek Świszczowski
6

Eingebaute Typen

Wenn Sie einem Ressourcenwörterbuch heute Objekte einfacher Typen wie Zeichenfolge oder Doppel hinzufügen möchten, müssen Sie die erforderlichen CLR-Namespaces einem XML-Namespace zuordnen. In XAML 2009 gibt es viele einfache Typen, die in der XAML-Sprache enthalten sind.

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

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

Die folgenden Typen sind in der XAML-Sprache enthalten:

<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/> 
Sauron
quelle
Dies funktioniert nicht, wenn WPF zur Verarbeitung von XAML verwendet wird. msdn.microsoft.com/en-us/library/ee792007.aspx
scobi
6

Einfache Objektreferenzen mit {x: Referenz}

Wenn Sie heute eine Objektreferenz erstellen möchten, müssen Sie eine Datenbindung durchführen und die Quelle mit einem Elementnamen deklarieren. In XAML 2009 können Sie die neue Markup-Erweiterung {x: Reference} verwenden

<!-- 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" />
Sauron
quelle
Es ist erwähnenswert, dass es sich zwar x:Referenceum eine XAML 2009-Sprachfunktion handelt, es jedoch einige Szenarien gibt, in denen sie auch in kompiliertem XAML funktioniert. Es funktioniert jedoch nicht überall und kann die XAML-Designeransicht beschädigen.
Mike Strobel
1
@ MikeStrobel: Es funktioniert so ziemlich überall, und es ist mir egal, ob Designer brechen.
HB
6

Verwendung von Systemfarben

<Border Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
Siehe scharf
quelle
3
Die Angabe als DynamicResource ist wichtig, da der Benutzer die Systemfarben ändern kann, während Ihre Anwendung ausgeführt wird.
M. Dudley
3

Unterstützung für beliebige Wörterbuchschlüssel

In XAML 2006 wurden alle expliziten x: Key-Werte als Zeichenfolgen behandelt. In XAML 2009 können Sie einen beliebigen Schlüsseltyp definieren, indem Sie den Schlüssel in ElementSyntax schreiben.

<!-- 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>
Sauron
quelle
2

Legen Sie einen ValidationError nach Code fest

Eine ValidatioRule in einer BindingExpression wird nur ausgelöst, wenn sich die Zielseite der Bindung ändert. Wenn Sie einen Validierungsfehler anhand des Codes festlegen möchten, können Sie das folgende Snippet verwenden.

Stellen Sie den Validierungsfehler ein

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

Löschen Sie den Validierungsfehler

Validation.ClearInvalid(textBox.GetBindingExpression(TextBox.TextProperty));
Sauron
quelle
2

Die Fähigkeit, UIElement (s) in einen TextBlock zu stopfen

Ich weiß nicht, wie nützlich dies ist (es gilt jedoch als versteckt) ... aber es hat mich sicher überrascht, als ich es zum ersten Mal traf :

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

Sie könnten argumentieren, dass das folgende xaml nützlich sein könnte (dh eine Grafik am Ende eines Textes einfügen):

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

Das obige xaml rendert wie folgt:

Hallo Welt

cplotts
quelle
1

Debuggen von Animationen

Häufige Fehler

Wenn die folgende Fehlermeldung angezeigt wird: '(0). (1)' kann auf einer unveränderlichen Objektinstanz nicht animiert werden. Es kann sein, dass Sie auf eine der folgenden Einschränkungen stoßen:

  • Sie animieren eine Abhängigkeitseigenschaft, ohne einen lokalen Wert festzulegen
  • Sie animieren eine Abhängigkeitseigenschaft, deren aktueller Wert in einer anderen Assembly definiert ist, die nicht mit dem Ressourcenwörterbuch zusammengeführt wird.
  • Sie animieren einen Wert, der derzeit datengebunden ist
Sauron
quelle
1

Bindung ohne INotifyPropertyChanged oder DependencyProperties

Wie hier erläutert , können Sie eine einfache CLR-Objekteigenschaft ohne INotifyPropertyChanged binden, und es funktioniert einfach .

Hier ist der Forumpost, auf den ich mich beziehe.

Zitat:

[...] Die Datenbindungs-Engine von WPF bindet Daten an die PropertyDescriptor-Instanz, die die Quelleigenschaft umschließt, wenn das Quellobjekt ein einfaches CLR-Objekt ist und keine INotifyPropertyChanged-Schnittstelle implementiert. Die Datenbindungs-Engine versucht, das Ereignis "Eigenschaft geändert" über die PropertyDescriptor.AddValueChanged () -Methode zu abonnieren. Wenn das an die Zieldaten gebundene Element die Eigenschaftswerte ändert, ruft die Datenbindungs-Engine die PropertyDescriptor.SetValue () -Methode auf, um den geänderten Wert zurück in die Quelleigenschaft zu übertragen, und löst gleichzeitig das ValueChanged-Ereignis aus, um andere Abonnenten zu benachrichtigen (in diesem Fall Die anderen Abonnenten sind die TextBlocks in der ListBox.

Wenn Sie INotifyPropertyChanged implementieren, sind Sie voll verantwortlich dafür, die Änderungsbenachrichtigung in jedem Setter der Eigenschaften zu implementieren, für die Daten an die Benutzeroberfläche gebunden werden müssen. Andernfalls wird die Änderung nicht wie erwartet synchronisiert. [...]

Hier ist ein weiterer großartiger und detaillierter Artikel zu diesem Thema.

Beachten Sie, dass dies nur bei Verwendung der Bindung funktioniert . Wenn Sie die Werte aus dem Code aktualisieren , wird die Änderung nicht benachrichtigt . [...]

Die Implementierung von INotifyPropertyChanged kann einiges an langwieriger Entwicklungsarbeit sein. Sie müssen diese Arbeit jedoch gegen den Laufzeit-Footprint (Speicher und CPU) Ihrer WPF-Anwendung abwägen. Wenn Sie INPC selbst implementieren, sparen Sie Laufzeit-CPU und Speicher .

UrbanEsc
quelle