Recursos ocultos do WPF e XAML?

123

Aqui está um grande número de recursos ocultos discutidos para vários idiomas. Agora estou curioso sobre alguns recursos ocultos do XAML e WPF?

Um que encontrei é o evento de clique no cabeçalho de um ListView

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

A propriedade GridViewColumnHeader.Click não está listada.

Alguns dos recursos relevantes até agora:

Veja também:

  1. Recursos ocultos do C #
  2. Recursos ocultos do Python
  3. Recursos ocultos do ASP.NET
  4. Recursos ocultos do Perl
  5. Recursos ocultos do Java
  6. Recursos ocultos do VB.NET
  7. Recursos ocultos do PHP
  8. Recursos ocultos do Ruby
  9. Recursos ocultos de C
  10. E assim por diante........
Sauron
fonte
7
Dê uma olhada aqui msdn.microsoft.com/en-us/library/… . O evento click é herdado do ButtonBase. O que você está descrevendo são Eventos anexados, um conceito bastante poderoso no WPF ( msdn.microsoft.com/en-us/library/bb613550.aspx ). Dessa forma, você pode fazer <Grid Button.Click> com 100 botões em uma grade e apenas 1 manipulador.
Sorskoot 14/07/2009
1
No começo eu era como "oh, aqui vamos nós de novo", mas então eu aprendi alguma coisa nas respostas, então eu ter tudo de volta: o: o
Sam Harwell
1
deve ser uma comunidade wiki
tsilb
2
@tsilb Eu não acho que deveria ser wiki comunidade, têm olhada neste link meta.stackexchange.com/questions/392/...
Prashant Cholachagudda

Respostas:

87

Multibinding (combinado com StringFormat):

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat="{}{0}, {1}">
      <Binding Path="LastName" />
      <Binding Path="FirstName" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>
Julien Poulin
fonte
1
impressionante :-) a menos que você esteja usando o silverlight 4 ou anterior. dedos cruzados para v5
Simon_Weaver 11/11
5
Isso é ótimo, mas eu ficaria tentado a não fazê-lo. Se eu precisar construir uma string, classificaria isso como lógica e gostaria de testar a saída da unidade. Às vezes, coisas assim são melhores no modelo de exibição como uma string.Format ().
Iain Holder
58

Há também o truque PresentationTraceSources.TraceLevel para depurar o que está acontecendo com as ligações em qualquer cenário específico. Tudo o que você precisa fazer é referenciar o espaço de nome System.Diagnostics no assembly WindowsBase

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

e adicione o seguinte à expressão de ligação:

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

O log será assim:

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
fonte
4
No VisualStudio 2010, você precisa definir o nível das configurações de rastreamento como aviso! Veja stackoverflow.com/questions/2802662/…
WaltiD
44

3.5sp1 introduziu TargetNullValue nas ligações. Isso definirá a propriedade vinculada como Nulo se o valor for inserido e se sua propriedade for Nula, ele exibirá esse valor.

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

3.5sp1 introduziu StringFormat em expressões de ligação, por exemplo

<TextBox Text="{Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}" />
Bryan Anderson
fonte
Não consigo expressar em palavras o quanto eu amo esse recurso. Eu odiava ter toneladas de conversores de valor por aí.
Rob
Sim, é facilmente adicionado um dos recursos que economizam mais tempo. Especialmente quando combinados com o TargetNullValue, muitos problemas desaparecem.
11139 Bryan Anderson
6
Colocar aspas simples ao redor do StringFormat deve remover alguns avisos do compilador -Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"
Ryan Versaw
É bom saber, eu me acostumei apenas a ignorá-los.
11139 Bryan Anderson
1
Eu estava tentando transmitir que qualquer sequência de formatação arbitrária funcionará. Eu acredito que a versão internacionalizada seria StringFormat = '{} {0: d}' neste caso.
Bryan Anderson
29

Às vezes, você recebe uma string muito longa para ser exibida no rótulo. Nesse caso, podemos usar a TextTrimmingpropriedade de TextBlockpara mostrar elipses

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

Link MSDN

Prashant
fonte
Considere a adição de uma dica de ferramenta em tal caso: tranxcoder.wordpress.com/2008/10/12/...
surfen
27

Adicionando efeito Aero à janela

  <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
fonte
1
Adicionado o código, mas ainda não adiciona o efeito Aero. Estou esquecendo de algo?
Elmo
21

Genéricos em XAML com x: TypeArguments

Se você quiser usar um ObservableCollection em XAML, precisará criar um tipo derivado de ObservableCollection, porque você não pode declará-lo em XAML. Com o XAML 2009, você pode usar o atributo x: TypeArguments para definir o tipo de um 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
fonte
1
Infelizmente, x: TypeArguments só está disponível em arquivos XAML soltos e os que não compilados :(
kevindaub
Sim, apenas xaml solto :( Para a maioria dos desenvolvedores do WPF, o XAML2009 é inútil.
Grigory
19

Mostrar dica de ferramenta em um controle desativado

O Wpf permite mostrar a dica de ferramenta em um controle, se estiver no estado desabilitado.

Por exemplo

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

Uso de construtores não padrão com argumentos x:

No XAML 2006, os objetos devem ter um construtor público padrão para usá-los. No XAML 2009, você pode transmitir argumentos do construtor usando a sintaxe x: Arguments.

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

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

Não é realmente um recurso oculto, mas com o WPF / XAML você recebe Bea Stollnitz e Josh Smith . Rainha e rei da programação WPF / XAML.

Bryan Anderson
fonte
3
O que é Karl? O Jack? Ou o Coringa?
cplotts
18

Extensões de marcação e propriedades anexadas são meus recursos favoritos, pois permitem estender o "vocabulário" XAML de uma maneira muito elegante.

Extensões de marcação

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

Propriedades anexadas

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

...

Origem para GridViewSort (btw, usa o GridViewColumnHeader.Clickevento mencionado por Ortus)

Thomas Levesque
fonte
A fonte está WinUtil.EnableAeroGlassdisponível em algum lugar?
Oskar
Sim, mas mudou muito desde que eu publiquei isso ... Agora existem 2 propriedades, EnableBlur e GlassFrameMargins. Você pode encontrar o código aqui: projets.developpez.com/projects/dvp-net/repository/entry/trunk/…
Thomas Levesque
15

Você pode consultar tipos aninhados em XAML usando o sinal de mais ( +). Por exemplo, se tivéssemos essa classe:

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

Podemos nos referir SomeValueno XAML usando a seguinte sintaxe:

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

Essa sintaxe não está documentada no MSDN e não é oficialmente suportada. Alguém perguntou sobre isso nos fóruns do MSDN e aparentemente isso quebra o WPF Designer do VS2010. Foi relatado no Microsoft Connect.

M. Dudley
fonte
14

Compartilhamento de tamanho de grade ( aqui está um bom exemplo). Para encurtar a história, você pode ter colunas e linhas de grade compartilhando tamanhos, mesmo em diferentes grades. Isso será inestimável para todas as pessoas que estão usando DataGrids sem a necessidade de editar os dados no local.

Bryan Anderson
fonte
11

PriorityBinding . Permite usar ligações assíncronas em uma ordem "primeiro a chegar, primeiro show":

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

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

Quando você tem um tipo que não tem construtor público, mas um método estático de fábrica, você precisava criar esse tipo de código no XAML 2006. Com o XAML 2009, você pode usar o atributo x: FactoryMethodx: Arguments para passar os valores do argumento.

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

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

Propriedades avançadas de "legenda"

Outra coisa que não está muito clara é o conteúdo de algumas propriedades às quais estamos acostumados, que contém apenas texto. Se a propriedade de um elemento da GUI for do tipo Objeto, é muito provável que você possa, em vez de apenas definir o texto, adicionar um painel de sua necessidade que inclua um conjunto de controles.

Um exemplo disso é o MenuItem, onde a Headerpropriedade (que normalmente contém apenas texto) pode conter um conjunto de elementos da GUI agrupados em um controle de painel (ou apenas um elemento da GUI, se você precisar de apenas um).

Observe também a Iconpropriedade no MenuItem. Normalmente, ele contém um elemento Image, mas também pode conter qualquer coisa!

<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>
admiração
fonte
7

Conversores XAML

A lista a seguir mostra conversores desenvolvidos pela comunidade WPF para converter diferentes formatos em XAML ou vice-versa.

Plug-in de exportação XAML do Adobe Illustrator

Conversor Adobe Photoshop para XAML

Plugin de Exportação XAML do Blender

Lightwave XAML Export Plugin

Exportação XAML do Visio

Conversor 3D Studio Max para XAML

Conversor Maya para XAML

Conversor Flash para XAML

Conversor SVG para XAML

Conversor WMF / EMF para XAML

Sauron
fonte
Também muito útil: GridLengthConverter, BooleanToVisibilityConverter, AlternationConverter tudo em System.Windows.Controls
Maciek Świszczowski
6

Tipos incorporados

Se você deseja adicionar objetos de tipos simples, como string ou duplo, a um dicionário de recursos hoje, precisa mapear os espaços de nomes clr necessários para espaços de nomes XML. No XAML 2009, muitos tipos simples estão incluídos na linguagem XAML.

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

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

Os seguintes tipos estão incluídos no idioma 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
fonte
Isso não funciona se você estiver usando o WPF para processar o XAML. msdn.microsoft.com/en-us/library/ee792007.aspx
scobi
6

Referências fáceis a objetos com {x: Reference}

Se você deseja criar uma referência de objeto hoje, precisará fazer uma ligação de dados e declarar a fonte com um ElementName. No XAML 2009, você pode usar a nova extensão de marcação {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
fonte
Vale ressaltar que, embora x:Referenceseja um recurso da linguagem XAML 2009, há alguns cenários em que ele também funcionará no XAML compilado. No entanto, ele não funciona em todos os lugares e pode interromper a exibição do designer XAML.
18711 Mike Strobel
1
@ MikeStrobel: Funciona praticamente em todos os lugares, e eu não me importo com a quebra de designers.
HB
6

Uso de cores do sistema

<Border Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
SeeSharp
fonte
3
Especificá-lo como um DynamicResource é importante porque o usuário pode alterar as cores do sistema enquanto o aplicativo está em execução.
M. Dudley
3

Suporte para chaves de dicionário arbitrário

No XAML 2006, todos os valores explícitos de x: Key foram tratados como cadeias. No XAML 2009, você pode definir qualquer tipo de chave que desejar, escrevendo a chave no 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
fonte
2

Definir um ValidationError por código

Um ValidatioRule em um BindingExpression é acionado apenas quando o lado de destino da ligação é alterado. Se você deseja definir um erro de validação por código, pode usar o seguinte snippet.

Defina o erro de validação

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

Limpe o erro de validação

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

A capacidade de agrupar UIElement (s) em um TextBlock

Eu não sei o quão útil (embora se qualifique como oculto) isso é ... mas com certeza me pegou de surpresa quando eu o encontrei :

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

Você pode argumentar que o seguinte xaml pode ser útil (por exemplo, colocar um gráfico no final de algum 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>

O xaml acima é renderizado da seguinte maneira:

Olá Mundo

cplotts
fonte
1

Depurando animações

Erros comuns

Se você receber o seguinte erro: Não é possível animar '(0). (1)' em uma instância de objeto imutável. pode ser que você tenha uma das seguintes limitações:

  • Você está animando uma propriedade de dependência sem definir um valor local
  • Você está animando uma propriedade de dependência cujo valor atual é definido em outro assembly que não é mesclado no dicionário de recursos.
  • Você está animando um valor atualmente associado ao banco de dados
Sauron
fonte
1

Ligação sem INotifyPropertyChanged ou DependencyProperties

Conforme discutido aqui, você pode vincular uma propriedade simples do objeto CLR sem INotifyPropertyChanged e funcionará apenas .

Aqui está o fórum estou me referindo.

Citar:

[...] O mecanismo de ligação de dados do WPF vinculará os dados à instância PropertyDescriptor que agrupa a propriedade de origem se o objeto de origem for um objeto CLR simples e não implementar a interface INotifyPropertyChanged. E o mecanismo de ligação de dados tentará se inscrever no evento alterado de propriedade por meio do método PropertyDescriptor.AddValueChanged (). E quando o elemento vinculado aos dados de destino alterar os valores da propriedade, o mecanismo de ligação de dados chamará o método PropertyDescriptor.SetValue () para transferir o valor alterado de volta para a propriedade de origem e aumentará simultaneamente o evento ValueChanged para notificar outros assinantes (nesta instância, os outros assinantes serão os TextBlocks na ListBox.

E se você estiver implementando INotifyPropertyChanged, será totalmente responsável por implementar a notificação de alteração em cada setter das propriedades que precisam ser dados vinculados à interface do usuário. Caso contrário, a alteração não será sincronizada conforme o esperado. [...]

Aqui está outro excelente e detalhado artigo sobre o assunto.

Observe que isso só funciona ao usar a ligação . Se você atualizar os valores do código , a alteração não será notificada . [...]

A implementação de INotifyPropertyChanged pode ser um bom trabalho de desenvolvimento tedioso. No entanto, você precisará pesar esse trabalho em relação ao espaço de tempo de execução (memória e CPU) do seu aplicativo WPF. A implementação do INPC você economizará CPU e memória em tempo de execução .

UrbanEsc
fonte