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

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>

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 

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

44

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

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

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


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>

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

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

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>


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)


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.


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.


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>

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

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>

7

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

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

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

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>

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

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


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

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 .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.