Funzionalità nascoste di WPF e XAML?


123

Ecco un gran numero di funzionalità nascoste discusse per una varietà di lingue. Ora sono curioso di alcune funzionalità nascoste di XAML e WPF?

Uno che ho trovato è l'evento clic sull'intestazione di un ListView

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

La proprietà GridViewColumnHeader.Click non è elencata.

Alcune delle caratteristiche rilevanti finora:

Guarda anche:

  1. Funzionalità nascoste di C #
  2. Funzionalità nascoste di Python
  3. Funzionalità nascoste di ASP.NET
  4. Caratteristiche nascoste di Perl
  5. Caratteristiche nascoste di Java
  6. Funzionalità nascoste di VB.NET
  7. Funzionalità nascoste di PHP
  8. Caratteristiche nascoste di Ruby
  9. Caratteristiche nascoste di C
  10. E così via........

7
Dai un'occhiata qui msdn.microsoft.com/en-us/library/… . L'evento clic viene ereditato da ButtonBase. Ciò che stai descrivendo sono eventi allegati, un concetto piuttosto potente in WPF ( msdn.microsoft.com/en-us/library/bb613550.aspx ). In questo modo puoi fare <Grid Button.Click> con 100 pulsanti su una griglia e un solo gestore.
Sorskoot

1
All'inizio ero tipo "oh, ci risiamo", ma poi ho imparato qualcosa nelle risposte, quindi riprendo tutto: o: o
Sam Harwell,

1
dovrebbe essere wiki della comunità
tsilb

2
@tsilb Non penso che dovrebbe essere un wiki della comunità, dai un'occhiata a questo link meta.stackexchange.com/questions/392/…
Prashant Cholachagudda

Risposte:


87

Multibinding (combinato con StringFormat):

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

1
fantastico :-) a meno che tu non stia usando silverlight 4 o versioni precedenti. dita incrociate per v5
Simon_Weaver

5
Questo è fantastico, ma sarei tentato di NON farlo. Se ho bisogno di costruire una stringa, la classificherei come logica e vorrei testare l'output. Cose come questa a volte sono migliori nel modello di visualizzazione come string.Format ().
Iain Holder l'

58

C'è anche il trucco PresentationTraceSources.TraceLevel per eseguire il debug di ciò che sta accadendo con le associazioni in uno scenario particolare. Tutto quello che devi fare è fare riferimento allo spazio dei nomi System.Diagnostics nell'assembly WindowsBase

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

e quindi aggiungi quanto segue all'espressione di associazione:

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

Il registro sarà così:

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
In VisualStudio 2010 è necessario impostare il livello delle impostazioni di traccia su avviso! Vedere stackoverflow.com/questions/2802662/...
WaltiD

44

3.5sp1 ha introdotto TargetNullValue nelle associazioni. Ciò imposterà la proprietà associata a Null se il valore viene immesso e se la proprietà è Null, verrà visualizzato questo valore.

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

44

3.5sp1 ha introdotto StringFormat nelle espressioni di associazione, ad es

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

Non riesco a esprimere a parole quanto amo quella caratteristica. Odiavo avere tonnellate di convertitori di valore in giro.
Rob il

Sì, facilmente una delle funzionalità che fanno risparmiare più tempo. Soprattutto se combinato con TargetNullValue molti problemi scompaiono.
Bryan Anderson

6
L'inserimento di virgolette singole attorno a StringFormat dovrebbe rimuovere alcuni avvisi del compilatore -Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"
Ryan Versaw

Buono a sapersi, mi sono abituato a ignorarli.
Bryan Anderson

1
Stavo cercando di comunicare che qualsiasi stringa di formattazione arbitraria funzionerà. Credo che la versione internazionalizzata sarebbe StringFormat = '{} {0: d}' in questo caso.
Bryan Anderson

29

A volte ottieni una stringa troppo lunga per essere mostrata sull'etichetta. In questo caso possiamo fare uso della TextTrimmingproprietà di TextBlockper mostrare le ellissi

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

MSDN Link


Considerare l'aggiunta di un tooltip in tal caso: tranxcoder.wordpress.com/2008/10/12/...
Surfen

27

Aggiunta dell'effetto Aero a Window

  <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
Aggiunto il codice ma ancora non aggiunge l'effetto Aero. Mi sto perdendo qualcosa?
Elmo

21

Generics in XAML con x: TypeArguments

Se vuoi usare un ObservableCollection in XAML devi creare un tipo che derivi da ObservableCollection perché non puoi dichiararlo in XAML. Con XAML 2009 puoi usare l'attributo x: TypeArguments per definire il tipo di un tipo generico.

<!-- 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
Sfortunatamente, x: TypeArguments è disponibile solo in file xaml sciolti e non compilati :(
kevindaub

Sì, solo xaml sciolto :( Per la maggior parte degli sviluppatori WPF XAML2009 è inutile.
Grigory

19

Mostra la descrizione comando su un controllo disabilitato

Wpf permette di mostrare il tooltip su un controllo, se è in stato disabilitato.

Per esempio

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

19

Uso di costruttori non predefiniti con x: Arguments

In XAML 2006 gli oggetti devono avere un costruttore predefinito pubblico per utilizzarli. In XAML 2009 puoi passare gli argomenti del costruttore usando la sintassi x: Arguments.

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

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


18

Le estensioni di markup e le proprietà associate sono le mie funzionalità preferite, ti consentono di estendere il "vocabolario" XAML in un modo molto elegante.

Estensioni di markup

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

Proprietà allegate

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

...

Sorgente per GridViewSort (a proposito, utilizza l' GridViewColumnHeader.Clickevento menzionato da Ortus)


La fonte per è WinUtil.EnableAeroGlassdisponibile da qualche parte?
Oskar

Sì, ma è cambiato molto da quando ho pubblicato questo ... Ora ci sono 2 proprietà, EnableBlur e GlassFrameMargins. Puoi trovare il codice qui: projets.developpez.com/projects/dvp-net/repository/entry/trunk/…
Thomas Levesque

15

Puoi fare riferimento a tipi nidificati in XAML utilizzando il segno più ( +). Ad esempio, se avessimo questa classe:

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

Potremmo fare riferimento SomeValuein XAML utilizzando la seguente sintassi:

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

Questa sintassi non è documentata su MSDN e non è ufficialmente supportata. Qualcuno ha chiesto informazioni sui forum MSDN e apparentemente rompe il WPF Designer di VS2010. È stato segnalato su Microsoft Connect.


14

Condivisione delle dimensioni della griglia ( ecco un buon esempio). Per farla breve, puoi avere colonne della griglia e righe che condividono dimensioni, anche su diverse griglie. Ciò sarà inestimabile per tutte le persone là fuori che utilizzano DataGrids senza la necessità di modificare i dati sul posto.


11

PriorityBinding . Ti consente di utilizzare associazioni asincrone in un ordine "primo arrivato, primo spettacolo":

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

10

Uso di metodi di fabbrica statici con x: FactoryMethod

Quando si dispone di un tipo che non ha un costruttore pubblico ma un metodo factory statico, è stato necessario creare quel tipo nel codice in XAML 2006. Con XAML 2009 è possibile utilizzare l'attributo x: FactoryMethodx: Arguments per passare i valori degli argomenti.

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

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

7

Proprietà "didascalia" avanzate

Un'altra cosa che non è molto chiara è il contenuto di alcune proprietà a cui siamo abituati contiene solo testo. Se la proprietà di un elemento della GUI è di tipo Object, è molto probabile che tu possa, invece di impostare solo il testo, aggiungere un pannello di tua necessità che includa una serie di controlli.

Un esempio di ciò è MenuItem, dove la Headerproprietà (che normalmente contiene solo testo) può contenere un insieme di elementi della gui racchiusi in un pannello di controllo (o solo un elemento della gui se ne serve solo uno).

Notare anche la Iconproprietà in MenuItem. Questo normalmente contiene un elemento Immagine, ma anche questo può contenere qualsiasi cosa!

<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

anche molto utili: GridLengthConverter, BooleanToVisibilityConverter, AlternationConverter tutto in System.Windows.Controls
Maciek Świszczowski

6

Tipi incorporati

Se si desidera aggiungere oggetti di tipi semplici come string o double a un dizionario delle risorse oggi, è necessario mappare gli spazi dei nomi clr necessari a uno spazio dei nomi XML. In XAML 2009 abbiamo molti tipi semplici inclusi nel linguaggio XAML.

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

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

I seguenti tipi sono inclusi nel linguaggio 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/> 

Questo non funziona se si usa WPF per elaborare XAML. msdn.microsoft.com/en-us/library/ee792007.aspx
scobi

6

Riferimenti a oggetti facili con {x: Reference}

Se vuoi creare un riferimento a un oggetto oggi, devi eseguire un'associazione dati e dichiarare la sorgente con un ElementName. In XAML 2009 puoi utilizzare la nuova estensione di markup {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" />

Vale la pena notare che sebbene x:Referencesia una funzionalità del linguaggio XAML 2009, esistono alcuni scenari in cui funzionerà anche in XAML compilato. Tuttavia, non funziona ovunque e potrebbe interrompere la visualizzazione di progettazione XAML.
Mike Strobel

1
@MikeStrobel: Funziona praticamente ovunque, aae non me ne potrebbe importare di meno che i designer si rompano.
HB

6

Uso dei colori di sistema

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

3
Specificarlo come DynamicResource è importante perché l'utente può modificare i colori di sistema mentre l'applicazione è in esecuzione.
M. Dudley

3

Supporto per chiavi arbitrarie del dizionario

In XAML 2006 tutti i valori x: Key espliciti venivano trattati come stringhe. In XAML 2009 puoi definire qualsiasi tipo di chiave che preferisci scrivendo la chiave in 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

Impostare un ValidationError per codice

Una ValidatioRule in una BindingExpression si attiva solo quando il lato di destinazione dell'associazione cambia. Se desideri impostare un errore di convalida tramite codice, puoi utilizzare il seguente frammento.

Imposta l'errore di convalida

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

Cancella l'errore di convalida

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

2

La capacità di inserire UIElement (s) in un TextBlock

Non so quanto sia utile (si qualifica come nascosto) ... ma di sicuro mi ha colto di sorpresa quando l'ho incontrato per la prima volta :

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

Potresti sostenere che il seguente xaml potrebbe essere utile (cioè mettere un grafico alla fine di un testo):

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

Il precedente xaml viene visualizzato come segue:

Ciao mondo


1

Debug delle animazioni

Errori comuni

Se viene visualizzato il seguente errore: Impossibile animare "(0). (1)" su un'istanza di oggetto non modificabile. potrebbe essere che ti trovi in ​​una delle seguenti limitazioni:

  • Stai animando una proprietà di dipendenza senza impostare un valore locale
  • Si sta animando una proprietà di dipendenza il cui valore corrente è definito in un altro assembly che non è stato unito al dizionario risorse.
  • Stai animando un valore che è attualmente associato a dati

1

Associazione senza INotifyPropertyChanged o DependencyProperties

Come discusso qui , puoi associare una semplice proprietà di oggetto CLR senza INotifyPropertyChanged e funzionerà .

Ecco il Forumpost mi riferisco.

Citazione:

[...] Il motore di data binding di WPF eseguirà il binding dei dati all'istanza PropertyDescriptor che avvolge la proprietà source se l'oggetto source è un semplice oggetto CLR e non implementa l'interfaccia INotifyPropertyChanged. E il motore di data binding proverà a sottoscrivere l'evento di modifica della proprietà tramite il metodo PropertyDescriptor.AddValueChanged (). E quando l'elemento associato ai dati di destinazione modifica i valori della proprietà, il motore di associazione dei dati chiamerà il metodo PropertyDescriptor.SetValue () per trasferire il valore modificato alla proprietà di origine e contemporaneamente solleverà l'evento ValueChanged per notificare agli altri abbonati (in questo caso, gli altri abbonati saranno i TextBlock all'interno del ListBox.

E se stai implementando INotifyPropertyChanged, sei pienamente responsabile di implementare la notifica di modifica in ogni setter delle proprietà che deve essere associato ai dati all'interfaccia utente. In caso contrario, la modifica non verrà sincronizzata come previsto. [...]

Ecco un altro articolo fantastico e dettagliato sull'argomento.

Nota che funziona solo quando si utilizza l'associazione . Se aggiorni i valori dal codice , la modifica non verrà notificata . [...]

L'implementazione di INotifyPropertyChanged può essere un bel po 'di noioso lavoro di sviluppo. Tuttavia, dovrai valutare questo lavoro rispetto al footprint di runtime (memoria e CPU) della tua applicazione WPF. L'implementazione di INPC da soli farà risparmiare CPU e memoria di runtime .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.