Fonctionnalités cachées de WPF et XAML?


123

Voici un grand nombre de fonctionnalités cachées discutées pour une variété de langues. Maintenant, je suis curieux de connaître certaines fonctionnalités cachées de XAML et WPF?

Un que j'ai trouvé est l'événement de clic d'en-tête d'un ListView

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

La propriété GridViewColumnHeader.Click n'est pas répertoriée.

Certaines des fonctionnalités pertinentes à ce jour:

Voir également:

  1. Fonctionnalités cachées de C #
  2. Fonctionnalités cachées de Python
  3. Fonctionnalités cachées d'ASP.NET
  4. Fonctionnalités cachées de Perl
  5. Fonctionnalités cachées de Java
  6. Fonctionnalités cachées de VB.NET
  7. Fonctionnalités cachées de PHP
  8. Fonctionnalités cachées de Ruby
  9. Fonctionnalités cachées de C
  10. Etc........

7
Jetez un œil ici msdn.microsoft.com/en-us/library/… . L'événement click est hérité de ButtonBase. Ce que vous décrivez sont des événements attachés, un concept assez puissant dans WPF ( msdn.microsoft.com/en-us/library/bb613550.aspx ). De cette façon, vous pouvez faire <Grid Button.Click> avec 100 boutons sur une grille et un seul gestionnaire.
Sorskoot le

1
Au début, je me suis dit "oh, on y va encore", mais ensuite j'ai appris quelque chose dans les réponses alors je reprends tout: o: o
Sam Harwell

1
devrait être wiki communautaire
tsilb

2
@tsilb Je ne pense pas que cela devrait être un wiki communautaire, regardez ce lien meta.stackexchange.com/questions/392/…
Prashant Cholachagudda

Réponses:


87

Multibinding (combiné avec StringFormat):

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

1
génial :-) sauf si vous utilisez silverlight 4 ou une version antérieure. croiser les doigts pour la v5
Simon_Weaver

5
C'est génial, mais je serais tenté de NE PAS le faire. Si j'ai besoin de créer une chaîne, je la classerais comme logique et je voudrais tester la sortie unitaire. Des trucs comme celui-ci sont parfois mieux dans le modèle de vue sous forme de chaîne.Format ().
Iain Holder

58

Il existe également une astuce PresentationTraceSources.TraceLevel pour déboguer ce qui se passe avec les liaisons dans un scénario particulier. Tout ce que vous avez à faire est de référencer l'espace de noms System.Diagnostics dans l'assembly WindowsBase

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

puis ajoutez ce qui suit à l'expression de liaison:

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

Le journal sera comme ceci:

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
Dans VisualStudio 2010, vous devez définir le niveau des paramètres de trace sur avertissement! Voir stackoverflow.com/questions/2802662/…
WaltiD

44

3.5sp1 a introduit TargetNullValue dans les liaisons. Cela définira la propriété liée à Null si la valeur est entrée et si votre propriété est Null, elle affichera cette valeur.

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

44

3.5sp1 a introduit StringFormat dans les expressions de liaison, par exemple

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

Je ne peux pas dire à quel point j'aime cette fonctionnalité. Je détestais avoir des tonnes de convertisseurs de valeur qui traînent.
Rob

Ouais, facilement l'une des fonctionnalités les plus rapides ajoutées. Surtout lorsqu'il est combiné avec TargetNullValue, de nombreux problèmes disparaissent.
Bryan Anderson le

6
Mettre des guillemets simples autour du StringFormat devrait supprimer certains avertissements du compilateur -Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"
Ryan Versaw

Bon à savoir, je me suis habitué à les ignorer.
Bryan Anderson le

1
J'essayais de dire que toute chaîne de formatage arbitraire fonctionnera. Je crois que la version internationalisée serait StringFormat = '{} {0: d}' dans ce cas.
Bryan Anderson

29

Parfois, vous obtenez une chaîne trop longue pour être affichée sur l'étiquette. Dans ce cas, nous pouvons utiliser la TextTrimmingpropriété de TextBlockpour afficher les ellipses

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

Lien MSDN


Pensez à ajouter une info-bulle dans ce cas: tranxcoder.wordpress.com/2008/10/12/…
surfen

27

Ajout d'un effet Aero à la fenêtre

  <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
Ajout du code mais n'ajoute toujours pas l'effet Aero. Est-ce que je manque quelque chose?
Elmo

21

Génériques en XAML avec x: TypeArguments

Si vous souhaitez utiliser un ObservableCollection en XAML, vous devez créer un type qui dérive de ObservableCollection car vous ne pouvez pas le déclarer en XAML. Avec XAML 2009, vous pouvez utiliser l'attribut x: TypeArguments pour définir le type d'un type générique.

<!-- 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
Malheureusement, x: TypeArguments n'est disponible que dans les fichiers xaml lâches et non compilés :(
kevindaub

Oui, lâchez le xaml uniquement: (Pour la majorité des développeurs WPF, XAML2009 est inutile.
Grigory

19

Afficher l'info-bulle sur un contrôle désactivé

Wpf permet d'afficher une info-bulle sur un contrôle, s'il est à l'état désactivé.

Par exemple

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

19

Utilisation de constructeurs non par défaut avec x: Arguments

Dans XAML 2006, les objets doivent avoir un constructeur par défaut public pour les utiliser. Dans XAML 2009, vous pouvez transmettre des arguments de constructeur à l'aide de la syntaxe x: Arguments.

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

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


18

Les extensions de balisage et les propriétés attachées sont mes fonctionnalités préférées, elles vous permettent d'étendre le «vocabulaire» XAML d'une manière très élégante.

Extensions de balisage

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

Propriétés attachées

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

...

Source pour GridViewSort (btw, il utilise l' GridViewColumnHeader.Clickévénement mentionné par Ortus)


La source est-elle WinUtil.EnableAeroGlassdisponible quelque part?
Oskar

Oui, mais cela a beaucoup changé depuis que j'ai posté ceci ... Il y a maintenant 2 propriétés, EnableBlur et GlassFrameMargins. Vous pouvez trouver le code ici: projets.developpez.com/projects/dvp-net/repository/entry/trunk/…
Thomas Levesque

15

Vous pouvez faire référence à des types imbriqués en XAML à l'aide du signe plus ( +). Par exemple, si nous avions cette classe:

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

Nous pourrions faire référence SomeValueen XAML en utilisant la syntaxe suivante:

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

Cette syntaxe n'est pas documentée sur MSDN et n'est pas officiellement prise en charge. Quelqu'un a posé des questions à ce sujet sur les forums MSDN, et apparemment cela brise le concepteur WPF de VS2010. Il a été signalé sur Microsoft Connect.


14

Partage de la taille de la grille ( voici un bon exemple). En bref, vous pouvez avoir des colonnes de grille et des lignes de taille de partage, même sur différentes grilles. Ce sera inestimable pour toutes les personnes qui utilisent DataGrids sans avoir besoin de modifier les données en place.


11

PriorityBinding . Vous permet d'utiliser les liaisons asynchrones dans un ordre "premier arrivé, premier spectacle":

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

10

Utilisation de méthodes statiques d'usine avec x: FactoryMethod

Lorsque vous avez un type qui n'a pas de constructeur public mais une méthode de fabrique statique, vous deviez créer ce type dans le code en XAML 2006. Avec XAML 2009, vous pouvez utiliser l'attribut x: FactoryMethodx: Arguments pour transmettre les valeurs d'argument.

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

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

7

Propriétés avancées de "légende"

Une autre chose qui n'est pas très claire est le contenu de certaines propriétés auxquelles nous sommes habitués ne contenant que du texte. Si la propriété d'un élément GUI est de type Object, il est très probable que vous puissiez, au lieu de simplement définir le texte, ajouter un panneau de votre besoin qui comprend un ensemble de contrôles.

Un exemple de ceci est le MenuItem, où la Headerpropriété (qui ne contient normalement que du texte) peut contenir un ensemble d'éléments d'interface graphique enveloppés dans un contrôle de panneau (ou juste un élément d'interface graphique si vous n'en avez besoin que d'un seul).

Notez également la Iconpropriété sur le MenuItem. Celui-ci contient normalement un élément Image, mais il peut également contenir n'importe quoi!

<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

également très utile: GridLengthConverter, BooleanToVisibilityConverter, AlternationConverter tout dans System.Windows.Controls
Maciek Świszczowski

6

Types intégrés

Si vous souhaitez ajouter des objets de types simples tels que string ou double à un dictionnaire de ressources, vous devez aujourd'hui mapper les espaces de noms clr nécessaires à des espaces de noms XML. Dans XAML 2009, nous avons beaucoup de types simples qui sont inclus dans le langage XAML.

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

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

Les types suivants sont inclus dans le langage 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/> 

Cela ne fonctionne pas si vous utilisez WPF pour traiter XAML. msdn.microsoft.com/en-us/library/ee792007.aspx
scobi

6

Références d'objets faciles avec {x: Reference}

Si vous souhaitez créer une référence d'objet aujourd'hui, vous devez effectuer une liaison de données et déclarer la source avec un ElementName. Dans XAML 2009, vous pouvez utiliser la nouvelle extension de balisage {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" />

Il convient de noter que s'il x:References'agit d'une fonctionnalité de langage XAML 2009, il existe certains scénarios dans lesquels elle fonctionnera également en XAML compilé. Cependant, cela ne fonctionne pas partout et peut casser la vue du concepteur XAML.
Mike Strobel

1
@MikeStrobel: Cela fonctionne à peu près partout, et je me fiche de la rupture des designers.
HB

6

Utilisation des couleurs du système

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

3
Le spécifier en tant que DynamicResource est important car l'utilisateur peut modifier les couleurs système pendant que votre application est en cours d'exécution.
M. Dudley

3

Prise en charge des clés de dictionnaire arbitraires

Dans XAML 2006, toutes les valeurs x: Key explicites étaient traitées comme des chaînes. Dans XAML 2009, vous pouvez définir n'importe quel type de clé que vous aimez en écrivant la clé dans 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

Définir une ValidationError par code

Un ValidatioRule dans un BindingExpression se déclenche uniquement lorsque le côté cible de la liaison change. Si vous souhaitez définir une erreur de validation par code, vous pouvez utiliser l'extrait de code suivant.

Définir l'erreur de validation

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

Effacer l'erreur de validation

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

2

La possibilité de farcir des UIElement (s) dans un TextBlock

Je ne sais pas à quel point c'est utile (cela se qualifie comme caché) ... mais cela m'a certainement pris au dépourvu lorsque je l'ai rencontré pour la première fois :

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

Vous pourriez argumenter que le xaml suivant pourrait être utile (c'est-à-dire mettre un graphique à la fin d'un texte):

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

Le xaml ci-dessus se présente comme suit:

Bonjour le monde


1

Débogage des animations

Erreurs courantes

Si vous obtenez l'erreur suivante: Impossible d'animer «(0). (1)» sur une instance d'objet immuable. il se peut que vous soyez confronté à l'une des limitations suivantes:

  • Vous animez une propriété de dépendance sans définir de valeur locale
  • Vous animez une propriété de dépendance dont la valeur actuelle est définie dans un autre assembly qui n'est pas fusionné dans le dictionnaire de ressources.
  • Vous animez une valeur qui est actuellement liée aux données

1

Liaison sans INotifyPropertyChanged ou DependencyProperties

Comme indiqué ici, vous pouvez lier une propriété d'objet CLR simple sans INotifyPropertyChanged, et cela fonctionnera simplement .

Voici le Forumpost auquel je fais référence.

Citation:

[...] Le moteur de liaison de données de WPF liera les données à l'instance PropertyDescriptor qui encapsule la propriété source si l'objet source est un objet CLR simple et n'implémente pas l'interface INotifyPropertyChanged. Et le moteur de liaison de données essaiera de s'abonner à l'événement de modification de propriété via la méthode PropertyDescriptor.AddValueChanged (). Et lorsque l'élément lié aux données cible modifie les valeurs de propriété, le moteur de liaison de données appelle la méthode PropertyDescriptor.SetValue () pour transférer la valeur modifiée vers la propriété source, et il déclenche simultanément l'événement ValueChanged pour informer les autres abonnés (dans ce cas, les autres abonnés seront les TextBlocks dans la ListBox.

Et si vous implémentez INotifyPropertyChanged, vous êtes entièrement responsable de l'implémentation de la notification de modification dans chaque setter des propriétés qui doivent être des données liées à l'interface utilisateur. Sinon, la modification ne sera pas synchronisée comme prévu. [...]

Voici un autre excellent article détaillé sur le sujet.

Notez que cela ne fonctionne que lors de l'utilisation de la liaison . Si vous mettez à jour les valeurs à partir du code , la modification ne sera pas notifiée . [...]

La mise en œuvre d'INotifyPropertyChanged peut être un travail de développement fastidieux. Cependant, vous devrez évaluer ce travail par rapport à l'empreinte d'exécution (mémoire et processeur) de votre application WPF. La mise en œuvre d'INPC vous-même économisera le processeur et la mémoire d'exécution .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.