¿Características ocultas de WPF y XAML?

123

Aquí hay una gran cantidad de características ocultas discutidas para una variedad de idiomas. ¿Ahora tengo curiosidad sobre algunas características ocultas de XAML y WPF?

Uno que he encontrado es el evento de clic en el encabezado de un ListView

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

La propiedad GridViewColumnHeader.Click no está en la lista.

Algunas de las características relevantes hasta ahora:

Ver también:

  1. Características ocultas de C #
  2. Características ocultas de Python
  3. Características ocultas de ASP.NET
  4. Características ocultas de Perl
  5. Características ocultas de Java
  6. Características ocultas de VB.NET
  7. Características ocultas de PHP
  8. Características ocultas de Ruby
  9. Características ocultas de C
  10. Y así........
Sauron
fuente
77
Eche un vistazo aquí msdn.microsoft.com/en-us/library/… . El evento click se hereda de ButtonBase. Lo que está describiendo son eventos adjuntos, un concepto bastante poderoso en WPF ( msdn.microsoft.com/en-us/library/bb613550.aspx ). De esta manera, puede hacer <Grid Button.Click> con 100 botones en una cuadrícula y solo 1 controlador.
Sorskoot
1
Al principio estaba como "oh, aquí vamos de nuevo", pero luego aprendí algo en las respuestas, así que lo retiro todo: o: o
Sam Harwell
1
debe ser wiki de la comunidad
tsilb
2
@tsilb No creo que deba ser wiki comunitario, mira este enlace meta.stackexchange.com/questions/392/…
Prashant Cholachagudda

Respuestas:

87

Multibinding (combinado con StringFormat):

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat="{}{0}, {1}">
      <Binding Path="LastName" />
      <Binding Path="FirstName" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>
Julien Poulin
fuente
1
impresionante :-) a menos que estés usando Silverlight 4 o anterior. dedos cruzados para v5
Simon_Weaver
55
Esto es genial, pero estaría tentado a NO hacerlo. Si necesito construir una cadena, la clasificaría como lógica y me gustaría probar la salida de la unidad. Cosas como esta a veces son mejores en el modelo de vista como una cadena. Formato ().
Iain Holder
58

También hay un truco PresentationTraceSources.TraceLevel para depurar lo que está sucediendo con los enlaces en cualquier escenario particular. Todo lo que tiene que hacer es hacer referencia al espacio de nombres System.Diagnostics en el ensamblado de WindowsBase

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

y luego agregue lo siguiente a la expresión de enlace:

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

El registro será así:

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
fuente
44
¡En VisualStudio 2010 debe establecer el nivel de la configuración de seguimiento en advertencia! Ver stackoverflow.com/questions/2802662/…
WaltiD
44

3.5sp1 introdujo TargetNullValue en los enlaces. Esto establecerá la propiedad vinculada en Null si se ingresa el valor y si su propiedad es Null, mostrará este valor.

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

3.5sp1 introdujo StringFormat en expresiones de enlace, por ejemplo

<TextBox Text="{Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}" />
Bryan Anderson
fuente
No puedo expresar con palabras cuánto amo esa característica. Odiaba tener toneladas de convertidores de valor por ahí.
Rob
Sí, fácilmente se agregó una de las características más ahorradoras de tiempo. Especialmente cuando se combina con TargetNullValue, muchos problemas desaparecen.
Bryan Anderson el
66
Poner comillas simples alrededor de la StringFormat debería eliminar algunas advertencias del compilador -Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"
Ryan Versaw
Es bueno saber que me he acostumbrado a ignorarlos.
Bryan Anderson el
1
Estaba tratando de transmitir que cualquier cadena de formato arbitrario funcionará. Creo que la versión internacionalizada sería StringFormat = '{} {0: d}' en este caso.
Bryan Anderson
29

A veces se obtiene una cadena que es demasiado larga para mostrar en la etiqueta. En este caso podemos hacer uso de la TextTrimmingpropiedad de TextBlockmostrar elipses

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

Enlace MSDN

Prashant
fuente
Considerar la adición de un texto de ayuda en tal caso: tranxcoder.wordpress.com/2008/10/12/...
surfen
27

Agregar efecto Aero a la ventana

  <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
fuente
1
Agregó el código pero aún no agrega el efecto Aero. ¿Me estoy perdiendo de algo?
Elmo
21

Genéricos en XAML con x: TypeArguments

Si desea utilizar una ObservableCollection en XAML, debe crear un tipo que se derive de ObservableCollection porque no puede declararlo en XAML. Con XAML 2009 puede usar el atributo x: TypeArguments para definir el tipo de un tipo genérico.

<!-- 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
fuente
1
Desafortunadamente, x: TypeArguments solo está disponible en archivos xaml sueltos y no compilados :(
kevindaub
Sí, solo xaml suelto :( Para la mayoría de los desarrolladores de WPF, XAML2009 es inútil.
Grigory
19

Mostrar información sobre herramientas en un control deshabilitado

Wpf permite mostrar información sobre herramientas en un control, si está en estado deshabilitado.

Por ejemplo

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

Uso de constructores no predeterminados con x: argumentos

En XAML 2006, los objetos deben tener un constructor público predeterminado para usarlos. En XAML 2009 puede pasar argumentos de constructor usando la sintaxis x: Arguments.

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

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

No es realmente una función oculta, pero con WPF / XAML obtienes Bea Stollnitz y Josh Smith . Reina y Rey de la programación WPF / XAML.

Bryan Anderson
fuente
3
Que es Karl ¿La toma? O el Joker?
Cplotts
18

Las extensiones de marcado y las propiedades adjuntas son mis características favoritas, le permiten ampliar el "vocabulario" XAML de una manera muy elegante.

Extensiones de marcado

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

Propiedades adjuntas

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

...

Fuente para GridViewSort (por cierto, utiliza el GridViewColumnHeader.Clickevento mencionado por Ortus)

Thomas Levesque
fuente
¿La fuente está WinUtil.EnableAeroGlassdisponible en alguna parte?
Oskar
Sí, pero ha cambiado mucho desde que publiqué esto ... Ahora hay 2 propiedades, EnableBlur y GlassFrameMargins. Puede encontrar el código aquí: projets.developpez.com/projects/dvp-net/repository/entry/trunk/…
Thomas Levesque
15

Puede hacer referencia a tipos anidados en XAML utilizando el signo más ( +). Por ejemplo, si tuviéramos esta clase:

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

Podríamos referirnos SomeValueen XAML usando la siguiente sintaxis:

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

Esta sintaxis no está documentada en MSDN y no es oficialmente compatible. Alguien preguntó al respecto en los foros de MSDN, y aparentemente rompe el Diseñador WPF de VS2010. Se ha informado en Microsoft Connect.

M. Dudley
fuente
14

Compartir el tamaño de la cuadrícula ( aquí hay un buen ejemplo). En pocas palabras, puede hacer que las columnas y filas de la cuadrícula compartan tamaños, incluso en diferentes cuadrículas. Esto será invaluable para todas las personas que están usando DataGrids sin la necesidad de editar los datos en su lugar.

Bryan Anderson
fuente
11

PriorityBinding . Le permite utilizar enlaces asínicos en un orden de "primero en llegar primero en mostrar":

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

Uso de métodos de fábrica estáticos con x: FactoryMethod

Cuando tiene un tipo que no tiene un constructor público sino un método de fábrica estático, tuvo que crear ese tipo de código en XAML 2006. Con XAML 2009 puede usar el atributo x: FactoryMethodx: Arguments para pasar los valores del argumento.

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

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

Propiedades avanzadas de "subtítulos"

Otra cosa que no está muy clara es que el contenido de algunas propiedades a las que estamos acostumbrados contiene solo texto. Si la propiedad de un elemento GUI es de tipo Objeto, es muy probable que pueda, en lugar de simplemente configurar el texto, agregar un panel de su necesidad que incluya un conjunto de controles.

Un ejemplo de esto es el MenuItem, donde el Header propiedad (que normalmente solo contiene texto) puede contener un conjunto de elementos de GUI envueltos en un control de panel (o solo un elemento de GUI si necesita solo uno).

También tenga en cuenta la Iconpropiedad en el MenuItem. Esto normalmente contiene un elemento de imagen, ¡pero también puede contener cualquier 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>
asombro
fuente
7

Convertidores XAML

La siguiente lista muestra los convertidores desarrollados por la comunidad WPF para convertir diferentes formatos a XAML o viceversa.

Adobe Illustrator XAML Export Plugin

Adobe Photoshop al convertidor de XAML

Complemento de exportación Blender XAML

Lightwave XAML Export Plugin

Exportación de Visio XAML

Convertidor 3D Studio Max a XAML

Convertidor Maya a XAML

Convertidor de Flash a XAML

Convertidor SVG a XAML

Convertidor WMF / EMF a XAML

Sauron
fuente
también muy útil: GridLengthConverter, BooleanToVisibilityConverter, AlternationConverter todo en System.Windows.Controls
Maciek Świszczowski
6

Tipos incorporados

Si desea agregar objetos de tipos simples como cadena o doble a un diccionario de recursos hoy, necesita asignar los espacios de nombres clr necesarios a espacios de nombres XML. En XAML 2009 tenemos muchos tipos simples que se incluyen en el lenguaje XAML.

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

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

Los siguientes tipos se incluyen en el lenguaje 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/> 
Sauron
fuente
Esto no funciona si usa WPF para procesar XAML. msdn.microsoft.com/en-us/library/ee792007.aspx
scobi
6

Referencias de objetos fáciles con {x: Reference}

Si desea crear una referencia de objeto hoy, necesita hacer un enlace de datos y declarar la fuente con un ElementName. En XAML 2009 puede usar la nueva extensión de marcado {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" />
Sauron
fuente
Vale la pena señalar que, si bien x:Referencees una característica del lenguaje XAML 2009, hay algunos escenarios en los que funcionará también en XAML compilado. Sin embargo, no funciona en todas partes y puede romper la vista del diseñador XAML.
Mike Strobel
1
@ MikeStrobel: Funciona prácticamente en todas partes, y no podría importarme menos la ruptura de los diseñadores.
HB
6

Uso de colores del sistema

<Border Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
SeeSharp
fuente
3
Es importante especificarlo como DynamicResource porque el usuario puede cambiar los colores del sistema mientras se ejecuta su aplicación.
M. Dudley
3

Soporte para claves de diccionario arbitrarias

En XAML 2006, todos los valores explícitos de x: clave se trataron como cadenas. En XAML 2009, puede definir cualquier tipo de clave que desee escribiendo la clave en 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>
Sauron
fuente
2

Establecer un error de validación por código

Una ValidatioRule en una BindingExpression solo se activa cuando cambia el lado de destino del enlace. Si desea establecer un error de validación por código, puede usar el siguiente fragmento.

Establecer el error de validación

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

Borrar el error de validación

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

La capacidad de rellenar UIElement (s) en un TextBlock

No sé cuán útil (aunque califica como oculto) esto es ... pero seguro que me tomó por sorpresa cuando lo encontré por primera vez :

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

Podría argumentar que el siguiente xaml podría ser útil (es decir, poner un gráfico al final de algún texto):

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

El xaml anterior se muestra como el siguiente:

Hola Mundo

3 revoluciones
fuente
1

Depuración de animaciones

Errores comunes

Si obtiene el siguiente error: No se puede animar '(0). (1)' en una instancia de objeto inmutable. podría ser que se encuentre con una de las siguientes limitaciones:

  • Está animando una propiedad de dependencia sin establecer un valor local
  • Está animando una propiedad de dependencia cuyo valor actual se define en otro ensamblado que no está fusionado en el diccionario de recursos.
  • Estás animando un valor que actualmente está vinculado a datos
Sauron
fuente
1

Enlace sin INotifyPropertyChanged o DependencyProperties

Como se discutió aquí , puede vincular una propiedad de objeto CLR simple sin INotifyPropertyChanged, y simplemente funcionará .

Aquí está el Forumpost al que me refiero.

Citar:

[...] El motor de enlace de datos de WPF enlazará los datos con la instancia de PropertyDescriptor que envuelve la propiedad fuente si el objeto fuente es un objeto CLR simple y no implementa la interfaz INotifyPropertyChanged. Y el motor de enlace de datos intentará suscribirse al evento de cambio de propiedad a través del método PropertyDescriptor.AddValueChanged (). Y cuando el elemento enlazado a datos de destino cambie los valores de propiedad, el motor de enlace de datos llamará al método PropertyDescriptor.SetValue () para transferir el valor cambiado de nuevo a la propiedad de origen, y simultáneamente generará el evento ValueChanged para notificar a otros suscriptores (en este caso, los otros suscriptores serán los TextBlocks dentro del ListBox.

Y si está implementando INotifyPropertyChanged, es completamente responsable de implementar la notificación de cambio en cada configurador de las propiedades que deben estar vinculadas a la interfaz de usuario. De lo contrario, el cambio no se sincronizará como cabría esperar. [...]

Aquí hay otro gran y detallado artículo sobre el tema.

Tenga en cuenta que esto solo funciona cuando se usa el enlace . Si actualiza los valores del código , el cambio no será notificado . [...]

Implementar INotifyPropertyChanged puede ser un trabajo tedioso de desarrollo. Sin embargo, tendrá que sopesar ese trabajo contra la huella de tiempo de ejecución (memoria y CPU) de su aplicación WPF. La implementación de INPC usted mismo ahorrará tiempo de ejecución de CPU y memoria .

revs UrbanEsc
fuente