Ukryte funkcje WPF i XAML?

123

Oto duża liczba ukrytych funkcji omówionych w różnych językach. Teraz jestem ciekawy niektórych ukrytych funkcji XAML i WPF?

Jeden, który znalazłem, to zdarzenie kliknięcia nagłówka w ListView

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

Właściwość GridViewColumnHeader.Click nie jest wymieniona.

Niektóre z istotnych funkcji do tej pory:

Zobacz też:

  1. Ukryte funkcje języka C #
  2. Ukryte funkcje Pythona
  3. Ukryte funkcje ASP.NET
  4. Ukryte funkcje Perla
  5. Ukryte funkcje Java
  6. Ukryte funkcje VB.NET
  7. Ukryte funkcje PHP
  8. Ukryte funkcje Rubiego
  9. Ukryte funkcje C
  10. I tak dalej........
Sauron
źródło
7
Zajrzyj tutaj msdn.microsoft.com/en-us/library/… . Zdarzenie click jest dziedziczone z ButtonBase. To, co opisujesz, to dołączone zdarzenia, całkiem potężna koncepcja w WPF ( msdn.microsoft.com/en-us/library/bb613550.aspx ). W ten sposób możesz zrobić <Grid Button.Click> ze 100 przyciskami na siatce i tylko 1 handlerem.
Sorskoot,
1
Na początku pomyślałem „och, znowu zaczynamy”, ale potem nauczyłem się czegoś w odpowiedziach, więc cofam to wszystko: o: o
Sam Harwell
1
powinno być wiki społeczności
tsilb,
2
@tsilb Myślę, że nie powinno to być wiki społeczności, spójrz na ten link meta.stackexchange.com/questions/392/ ...
Prashant Cholachagudda

Odpowiedzi:

87

Multibinding (w połączeniu z StringFormat):

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat="{}{0}, {1}">
      <Binding Path="LastName" />
      <Binding Path="FirstName" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>
Julien Poulin
źródło
1
super :-), chyba że używasz Silverlight 4 lub starszego.
trzymam
5
To świetnie, ale kusiłabym się, aby tego NIE robić. Jeśli muszę zbudować ciąg, zaklasyfikowałbym go jako logikę i chciałbym przetestować jednostkowe dane wyjściowe. Takie rzeczy są czasami lepsze w modelu widoku jako ciąg.Format ().
Iain Holder
58

Istnieje również sztuczka PresentationTraceSources.TraceLevel do debugowania tego, co dzieje się z powiązaniami w dowolnym konkretnym scenariuszu. Wszystko, co musisz zrobić, to odwołać się do przestrzeni nazw System.Diagnostics w zestawie WindowsBase

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

a następnie dodaj następujące wyrażenie do wyrażenia wiążącego:

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

Dziennik będzie wyglądał następująco:

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
źródło
4
W VisualStudio 2010 musisz ustawić poziom ustawień śledzenia na ostrzeżenie! Zobacz stackoverflow.com/questions/2802662/…
WaltiD
44

3.5sp1 wprowadził TargetNullValue do powiązań. Spowoduje to ustawienie powiązanej właściwości na Null, jeśli wartość zostanie wprowadzona, a jeśli właściwość ma wartość Null, wyświetli tę wartość.

<TextBox Text="{Binding Total, TargetNullValue=$0.00}" />
Bryan Anderson
źródło
44

3.5sp1 wprowadził StringFormat do wyrażeń wiążących, np

<TextBox Text="{Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}" />
Bryan Anderson
źródło
Nie potrafię wyrazić słowami, jak bardzo kocham tę funkcję. Nienawidziłem mieć tony konwerterów wartości leżących wokół.
Rob
Tak, z pewnością jedna z dodanych funkcji zapewniających największą oszczędność czasu. Zwłaszcza w połączeniu z TargetNullValue wiele problemów znika.
Bryan Anderson
6
Umieszczenie pojedynczych cudzysłowów wokół StringFormat powinno usunąć niektóre ostrzeżenia kompilatora -Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"
Ryan Versaw
Dobrze wiedzieć, przyzwyczaiłem się do ignorowania ich.
Bryan Anderson
1
Próbowałem przekazać, że zadziała dowolny dowolny ciąg formatujący. Uważam, że w tym przypadku wersją międzynarodową byłaby StringFormat = '{} {0: d}'.
Bryan Anderson,
29

Czasami otrzymujesz ciąg, który jest zbyt długi, aby pokazać go na etykiecie. W tym przypadku możemy skorzystać z TextTrimmingwłaściwości of, TextBlockaby wyświetlić wielokropki

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

MSDN Link

Prashant
źródło
W takim przypadku rozważ dodanie podpowiedzi: tranxcoder.wordpress.com/2008/10/12/...
surfen
27

Dodanie efektu Aero do okna

  <Window.Resources>
    <ResourceDictionary Source="/PresentationFramework.Aero, Version=3.0.0.0, Culture=neutral, 
        PublicKeyToken=31bf3856ad364e35, ProcessorArchitecture=MSIL;component/themes/aero.normalcolor.xaml" />
</Window.Resources>
Saurona
źródło
1
Dodano kod, ale nadal nie dodaje efektu Aero. Czy coś mi brakuje?
Elmo,
21

Typy ogólne w XAML z x: TypeArguments

Jeśli chcesz użyć ObservableCollection w XAML, musisz utworzyć typ, który pochodzi od ObservableCollection, ponieważ nie możesz zadeklarować go w XAML. W języku XAML 2009 można użyć atrybutu x: TypeArguments, aby zdefiniować typ typu ogólnego.

<!-- 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
źródło
1
Niestety x: TypeArguments jest dostępny tylko w luźnych plikach xaml i
nieskompilowanych
Tak, tylko luźny xaml :( Dla większości programistów WPF XAML2009 jest bezużyteczny.
Grigorij
19

Pokaż etykietkę dla wyłączonej kontrolki

Wpf umożliwia wyświetlanie podpowiedzi na kontrolce, jeśli jest ona wyłączona.

Na przykład

<Button Content="Disabled Button" ToolTipService.ShowOnDisabled="True" IsEnabled="False" ToolTip="This is a disabled button"/> 
Sauron
źródło
19

Używanie konstruktorów innych niż domyślne z argumentami x:

W XAML 2006 obiekty muszą mieć publicznego konstruktora domyślnego, aby ich używać. W języku XAML 2009 można przekazywać argumenty konstruktora przy użyciu składni x: Arguments.

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

<!-- XAML 2009 -->
<DateTime>
    <x:Arguments>
        <x:Int64>100</x:Int64>
    </x:Arguments>
</DateTime>
Sauron
źródło
18

Niezbyt ukryta funkcja, ale dzięki WPF / XAML otrzymujesz Bea Stollnitz i Josh Smith . Królowa i król programowania WPF / XAML.

Bryan Anderson
źródło
3
Co to jest Karl? Jack? Albo Jokera?
cplotts
18

Rozszerzenia znaczników i dołączone właściwości to moje ulubione funkcje, które umożliwiają rozszerzenie „słownictwa” XAML w bardzo elegancki sposób.

Rozszerzenia znaczników

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

Załączone właściwości

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

...

Źródło GridViewSort (przy okazji używa GridViewColumnHeader.Clickzdarzenia wspomnianego przez Ortusa)

Thomas Levesque
źródło
Czy źródło WinUtil.EnableAeroGlassjest gdzieś dostępne?
Oskar
Tak, ale wiele się zmieniło, odkąd to opublikowałem ... Są teraz 2 właściwości, EnableBlur i GlassFrameMargins. Możesz znaleźć kod tutaj: projets.developpez.com/projects/dvp-net/repository/entry/trunk/…
Thomas Levesque
15

Możesz odwoływać się do typów zagnieżdżonych w XAML przy użyciu znaku plus ( +). Na przykład, gdybyśmy mieli tę klasę:

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

Możemy odwoływać się do SomeValuejęzyka XAML przy użyciu następującej składni:

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

Ta składnia nie jest udokumentowana w witrynie MSDN i nie jest oficjalnie obsługiwana. Ktoś zapytał o to na forach MSDN i najwyraźniej psuje WPF Designer VS2010. Zostało to zgłoszone w Microsoft Connect.

M. Dudley
źródło
14

Udostępnianie rozmiaru siatki ( oto dobry przykład). Krótko mówiąc, kolumny i wiersze siatki mogą mieć takie same rozmiary, nawet w różnych siatkach. Będzie to nieocenione dla wszystkich ludzi, którzy używają DataGrids bez konieczności edytowania danych w miejscu.

Bryan Anderson
źródło
11

PriorityBinding . Umożliwia korzystanie z asynowych wiązań w kolejności „kto pierwszy ten lepszy”:

<TextBlock.Text>
      <PriorityBinding FallbackValue="defaultvalue">
        <Binding Path="SlowestDP" IsAsync="True"/>
        <Binding Path="SlowerDP" IsAsync="True"/>
        <Binding Path="FastDP" />
      </PriorityBinding>
</TextBlock.Text>
Sergey Aldoukhov
źródło
10

Użycie statycznych metod fabryki z x: FactoryMethod

Jeśli masz typ, który nie ma konstruktora publicznego, ale statyczną metodę fabryki, musisz utworzyć ten typ w kodzie w XAML 2006. W przypadku języka XAML 2009 możesz użyć atrybutu x: FactoryMethodx: Arguments, aby przekazać wartości argumentów.

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

<!-- XAML 2009 -->
<Guid x:FactoryMethod="Guid.NewGuid" />
Sauron
źródło
7

Zaawansowane właściwości „podpisu”

Inną rzeczą, która nie jest zbyt jasna, jest zawartość niektórych właściwości, do których przywykliśmy, że zawiera tylko tekst. Jeśli właściwość elementu GUI jest typu Object, jest bardzo prawdopodobne, że zamiast tylko ustawiania tekstu, można dodać panel według potrzeb, zawierający zestaw elementów sterujących.

Przykładem tego jest MenuItem, gdzie Headerwłaściwość (która zwykle zawiera tylko tekst) może zawierać zestaw elementów gui opakowanych w kontrolkę panelu (lub tylko jeden element gui, jeśli potrzebujesz tylko jednego).

Zwróć także uwagę na Iconwłaściwość w MenuItem. Zwykle zawiera element Image, ale może też zawierać wszystko!

<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>
podziwu
źródło
7

Konwertery XAML

Na poniższej liście przedstawiono konwertery opracowane przez społeczność WPF w celu konwertowania różnych formatów na XAML lub odwrotnie.

Wtyczka Adobe Illustrator XAML Export

Konwerter Adobe Photoshop na XAML

Wtyczka Blender XAML Export

Wtyczka Lightwave XAML Export

Eksport Visio XAML

Konwerter 3D Studio Max na XAML

Konwerter Maya na XAML

Konwerter Flash na XAML

Konwerter SVG na XAML

Konwerter WMF / EMF na XAML

Sauron
źródło
również bardzo przydatne: GridLengthConverter, BooleanToVisibilityConverter, AlternationConverter wszystko w System.Windows.Controls
Maciek Świszczowski
6

Wbudowane typy

Jeśli chcesz dziś dodać obiekty prostego typu, takie jak string lub double do słownika zasobów, musisz zmapować potrzebne przestrzenie nazw clr na przestrzenie nazw XML. W XAML 2009 mamy wiele prostych typów, które są zawarte w języku XAML.

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

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

W języku XAML uwzględniono następujące typy:

<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/> 
Saurona
źródło
To nie działa, jeśli używasz WPF do przetwarzania XAML. msdn.microsoft.com/en-us/library/ee792007.aspx
scobi
6

Łatwe odniesienia do obiektów dzięki {x: Reference}

Jeśli chcesz dziś utworzyć odwołanie do obiektu, musisz wykonać powiązanie z danymi i zadeklarować źródło za pomocą elementu ElementName. W języku XAML 2009 możesz użyć nowego rozszerzenia znaczników {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
źródło
Warto zauważyć, że chociaż x:Referencejest to funkcja języka XAML 2009, istnieją pewne scenariusze, w których będzie działać również w skompilowanym XAML. Jednak nie działa wszędzie i może zepsuć widok projektanta XAML.
Mike Strobel
1
@MikeStrobel: Działa prawie wszędzie, aaa i nie obchodzi mnie, że projektanci się psują.
HB
6

Wykorzystanie kolorów systemu

<Border Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
SeeSharp
źródło
3
Określenie go jako DynamicResource jest ważne, ponieważ użytkownik może zmieniać kolory systemowe podczas działania aplikacji.
M. Dudley,
3

Obsługa arbitralnych kluczy słowników

W języku XAML 2006 wszystkie jawne wartości x: Key były traktowane jako ciągi. W XAML 2009 możesz zdefiniować dowolny typ klucza, pisząc klucz w 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
źródło
2

Ustaw ValidationError według kodu

ValidatioRule w BindingExpression jest wyzwalany tylko w przypadku zmiany strony docelowej powiązania. Jeśli chcesz ustawić błąd walidacji według kodu, możesz użyć następującego fragmentu kodu.

Ustaw błąd walidacji

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

Usuń błąd walidacji

Validation.ClearInvalid(textBox.GetBindingExpression(TextBox.TextProperty));
Sauron
źródło
2

Możliwość umieszczania elementów UIElement w TextBlock

Nie wiem, jak przydatne (kwalifikuje się jako ukryte) to jest ... ale z pewnością zaskoczyło mnie, gdy pierwszy raz na to wpadłem :

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

Możesz argumentować, że następujący xaml może być przydatny (np. Umieszczenie grafiki na końcu jakiegoś tekstu):

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

Powyższy xaml renderuje się następująco:

Witaj świecie

cplotts
źródło
1

Animacje debugowania

Powszechne błędy

Jeśli pojawi się następujący błąd: Nie można animować „(0). (1)” na niezmiennej instancji obiektu. może się zdarzyć, że napotkasz jedno z następujących ograniczeń:

  • Animujesz właściwość zależności bez ustawiania wartości lokalnej
  • Animujesz właściwość zależności, której bieżąca wartość jest zdefiniowana w innym zestawie, który nie jest scalony ze słownikiem zasobów.
  • Animujesz wartość, która jest aktualnie związana z danymi
Sauron
źródło
1

Wiązanie bez INotifyPropertyChanged lub DependencyProperties

Jak omówiono tutaj , możesz powiązać zwykłą właściwość obiektu CLR bez INotifyPropertyChanged i po prostu zadziała .

Oto Forumpost, do którego się odnoszę .

Zacytować:

[...] Silnik powiązań danych WPF będzie wiązał dane z wystąpieniem PropertyDescriptor, które otacza właściwość źródłową, jeśli obiekt źródłowy jest zwykłym obiektem CLR i nie implementuje interfejsu INotifyPropertyChanged. Silnik powiązań danych spróbuje zasubskrybować zdarzenie zmiany właściwości za pomocą metody PropertyDescriptor.AddValueChanged (). Gdy docelowy element powiązany z danymi zmieni wartości właściwości, silnik powiązania danych wywoła metodę PropertyDescriptor.SetValue () w celu przesłania zmienionej wartości z powrotem do właściwości źródłowej i jednocześnie zgłosi zdarzenie ValueChanged, aby powiadomić innych subskrybentów (w tym przypadku pozostali subskrybenci będą TextBlockami w ListBox.

A jeśli wdrażasz INotifyPropertyChanged, jesteś w pełni odpowiedzialny za zaimplementowanie powiadomienia o zmianie w każdym programie ustawiającym właściwości, które muszą być powiązane z danymi w interfejsie użytkownika. W przeciwnym razie zmiana nie zostanie zsynchronizowana zgodnie z oczekiwaniami. [...]

Oto kolejny świetny i szczegółowy artykuł na ten temat.

Zauważ, że działa to tylko podczas używania wiązania . Jeśli zaktualizujesz wartości z kodu , zmiana nie zostanie powiadomiona . […]

Wdrożenie INotifyPropertyChanged może być dość żmudną pracą programistyczną. Musisz jednak zważyć, że to działa w stosunku do środowiska uruchomieniowego (pamięci i procesora) aplikacji WPF. Samodzielne wdrożenie INPC pozwoli zaoszczędzić procesor i pamięć w czasie wykonywania .

UrbanEsc
źródło