Приховані особливості WPF та XAML?


123

Тут представлена ​​велика кількість прихованих функцій, що обговорюються для різних мов. Тепер мені цікаво про якісь приховані функції XAML та WPF?

Одне, що я знайшов, - це подія клацання заголовка ListView

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

Властивість GridViewColumnHeader.Click не вказана.

Деякі актуальні функції поки:

Дивитися також:

  1. Приховані функції C #
  2. Приховані особливості Python
  3. Приховані можливості ASP.NET
  4. Приховані риси Перла
  5. Приховані особливості Java
  6. Приховані особливості VB.NET
  7. Приховані особливості PHP
  8. Приховані риси Рубі
  9. Приховані особливості С
  10. І так далі........

7
Подивіться тут msdn.microsoft.com/en-us/library / ... . Подія натискання успадковується від ButtonBase. Те, що ви описуєте, - це додані події, досить потужна концепція WPF ( msdn.microsoft.com/en-us/library/bb613550.aspx ). Таким чином ви можете зробити <Grid Button.Click> за допомогою 100 кнопок на сітці та лише 1 обробкою.
Sorskoot

1
Спочатку я був на кшталт "ой, ми знову йдемо", але потім я дізнався щось у відповідях, тож я все повертаю назад: o: o
Сем Харвелл

1
повинні бути wiki спільноти
tsilb

2
@tsilb Я не думаю, що це має бути вікі спільноти, перегляньте це посилання meta.stackexchange.com/questions/392/…
Prashant Cholachagudda

Відповіді:


87

Мультизв'язування (у поєднанні зі StringFormat):

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

1
дивовижно :-), якщо ви не використовуєте Silverlight 4 або новіші. пальці схрещені для v5
Simon_Weaver

5
Це чудово, але я б спокусився НЕ зробити цього. Якщо мені потрібно побудувати рядок, я б класифікував це як логіку і хотів би перевірити вихід. Такі речі іноді краще переглядати в моделі перегляду як рядок.Format ().
Ієн Холдер

58

Існує також презентація PresentationTraceSources.TraceLevel, щоб налагодити те, що відбувається з прив’язками в будь-якому конкретному сценарії. Все, що вам потрібно зробити, - це посилання на простір імен System.Diagnostics у збірці WindowsBase

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

а потім додайте наступне до виразу зв'язування:

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

Журнал буде таким:

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
У VisualStudio 2010 потрібно встановити рівень налаштування сліду на попередження! Див stackoverflow.com/questions/2802662 / ...
WaltiD

44

3.5sp1 представив TargetNullValue до прив’язок. Це встановить прив’язане властивість до Null, якщо значення введене, а якщо ваше властивість - Null, воно відобразить це значення.

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

44

3.5sp1 ввів StringFormat у виразні зв'язки, наприклад

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

Я не можу сказати словами лише те, наскільки я люблю цю особливість. Я ненавидів, що навколо них лежать тонни перетворювачів цінності.
Роб

Так, легко додана одна з функцій збереження часу. Особливо в поєднанні з TargetNullValue багато проблем минає.
Брайан Андерсон

6
Якщо розмістити єдині лапки навколо StringFormat, слід видалити деякі попередження компілятора -Text={Binding Date, StringFormat='{}{0:MM/dd/yyyy}'}"
Ryan Versaw

Добре знати, я звик просто їх ігнорувати.
Брайан Андерсон

1
Я намагався донести, що будь-який довільний рядок форматування буде працювати. Я вважаю, що інтернаціоналізована версія в цьому випадку буде StringFormat = '{} {0: d}'.
Брайан Андерсон

29

Іноді ви отримуєте занадто довгий рядок для відображення на етикетці. У цьому випадку ми можемо скористатися TextTrimmingвластивістю TextBlockпоказу Ellipses

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

MSDN Посилання


Подумайте про додавання підказки в такому випадку: tranxcoder.wordpress.com/2008/10/12/…
surfen

27

Додавання ефекту Aero у вікно

  <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
Додано код, але все ще не додає ефекту Aero. Я щось пропускаю?
Елмо

21

Загальні дані в XAML з x: TypeArguments

Якщо ви хочете використовувати ObservableCollection в XAML, вам потрібно створити тип, який походить від ObservableCollection, оскільки ви не можете оголосити його в XAML. З XAML 2009 ви ​​можете використовувати атрибут x: TypeArguments для визначення типу загального типу.

<!-- 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
На жаль, x: TypeArguments доступний лише у вільних файлах
xaml,

Так, лише xaml :( Для більшості розробників WPF XAML2009 марний.
Григорій

19

Показати підказку на вимкненому елементі управління

Wpf дозволяє відображати підказку на контролі, якщо він знаходиться у відключеному стані.

Наприклад

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

19

Використання конструкторів за замовчуванням з x: Аргументи

У XAML 2006 об'єкти повинні мати публічний конструктор за замовчуванням, щоб використовувати їх. У XAML 2009 ви ​​можете передавати аргументи конструктора, використовуючи синтаксис x: Аргументи.

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

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


18

Розширення розмітки та додані властивості - це мої улюблені функції, вони дозволяють розширити "словниковий запас" XAML дуже елегантно.

Розширення розмітки

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

Приєднані властивості

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

...

Джерело для GridViewSort (btw, він використовує GridViewColumnHeader.Clickподію, згадану Ortus)


Чи WinUtil.EnableAeroGlassдоступне джерело десь?
Оскар

Так, але це значно змінилося з моменту публікації цього повідомлення ... Зараз є 2 властивості, EnableBlur та GlassFrameMargins. Ви можете знайти код тут: projets.developpez.com/projects/dvp-net/repository/entry/trunk/…
Томас Левеск

15

Ви можете посилатися на вкладені типи в XAML, використовуючи знак плюс ( +). Наприклад, якби у нас був цей клас:

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

Ми можемо посилатися на SomeValueXAML, використовуючи наступний синтаксис:

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

Цей синтаксис не задокументований у MSDN , і він офіційно не підтримується. Хтось запитав про це на форумах MSDN, і, мабуть, це порушує WSF Designer VS2010. Про це повідомляється на Microsoft Connect.


14

Обмін розмірами сітки ( ось хороший приклад). Якщо коротко розповісти, у вас можуть бути стовпці сітки та розміри рядків навіть у різних сітках. Це буде неоціненним для всіх людей, які використовують DataGrids без необхідності редагувати дані на місці.


11

PriorityBinding . Дозволяє використовувати прив’язки до асинів у порядку "перший прихід першим шоу":

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

10

Використання статичних заводських методів з x: FactoryMethod

Якщо у вас є тип, який не має загальнодоступного конструктора, а статичний заводський метод, вам довелося створити цей тип у коді в XAML 2006. З XAML 2009 ви ​​можете використовувати атрибут x: FactoryMethodx: Arguments для передачі значень аргументу.

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

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

7

Розширені властивості "підписів"

Інша річ, яка не дуже зрозуміла, - це вміст деяких властивостей, до яких ми звикли містити лише текст. Якщо властивість елемента GUI має тип Object, дуже ймовірно, що ви можете замість того, щоб просто встановити текст, додати потрібну панель, що включає набір елементів керування.

Прикладом цього є MenuItem, де Headerвластивість (яка зазвичай просто містить текст) може містити набір елементів gui, загорнуті в панель управління (або лише один елемент gui, якщо вам потрібен лише один).

Також відзначте Iconвластивість у меню MenuItem. Зазвичай він містить елемент зображення, але він також може містити все, що завгодно!

<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

Перетворювачі XAML

У наступному списку представлені перетворювачі, розроблені спільнотою WPF для перетворення різних форматів у XAML або навпаки.

Adobe Illustrator XAML плагін для експорту

Adobe Photoshop в XAML Converter

Плагін для експорту Blender XAML

Lightwave XAML плагін для експорту

Експорт Visio XAML

3D Studio Max в XAML конвертер

Майя в XAML конвертер

Flash в XAML конвертер

SVG в XAML конвертер

WMF / EMF в XAML конвертер


також дуже корисні: GridLengthConverter, BooleanToVisibilityConverter, AlternationConverter all in System.Windows.Controls
Maciek Świszczowski

6

Вбудовані типи

Якщо ви хочете сьогодні додати об’єкти простих типів, таких як рядок або подвійний, до словника ресурсів, вам потрібно зіставити потрібні простори імен clr в простори імен XML. У XAML 2009 ми маємо багато простих типів, які входять до мови XAML.

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

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

Наступні типи включені до мови 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/> 

Це не працює, якщо для обробки XAML використовується WPF. msdn.microsoft.com/en-us/library/ee792007.aspx
scobi

6

Легкі посилання на об’єкт із {x: Reference}

Якщо ви хочете створити посилання на об'єкт сьогодні, вам потрібно зробити прив'язку даних і оголосити джерело за допомогою ElementName. У XAML 2009 ви ​​можете використовувати нове розширення розмітки {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" />

Варто зазначити, що, хоча x:Referenceфункція мови XAML 2009, є деякі сценарії, де вона буде працювати і в складеному XAML. Однак він працює не скрізь, і це може порушити вигляд дизайнера XAML.
Майк Стробель

1
@MikeStrobel: Це працює майже скрізь, а я не можу менше дбати про те, щоб дизайнери зламали.
НВ

6

Використання системних кольорів

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

3
Вказати його як DynamicResource важливо, оскільки користувач може змінювати кольори системи під час роботи програми.
М. Дадлі

3

Підтримка ключів довільного словника

У XAML 2006 всі явні x: ключові значення розглядалися як рядки. У XAML 2009 ви ​​можете визначити будь-який тип ключа, який вам подобається, записавши ключ у 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

Встановіть ValidationError за кодом

Валідатіоруль у BindingExpression запускається лише тоді, коли змінюється цільова сторона зв'язування. Якщо ви хочете встановити помилку перевірки за кодом, ви можете скористатися наступним фрагментом.

Встановіть помилку перевірки

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

Очистити помилку перевірки

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

2

Можливість заповнити UIElement (s) в TextBlock

Я не знаю, наскільки це корисно (але це кваліфікується як приховане) це ... але це впевнено застало мене поза охороною, коли я вперше наткнувся на нього :

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

Ви можете стверджувати, що наступний xaml може бути корисним (тобто розміщення графіки в кінці деякого тексту):

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

Наведений вище xaml відображає наступне:

Привіт Світ


1

Налагодження анімації

Поширені помилки

Якщо ви отримаєте таку помилку: Неможливо анімувати "(0). (1)" на екземплярі об'єкта, що не змінюється. можливо, у вас виникло одне з таких обмежень:

  • Ви анімуєте властивість залежності, не встановлюючи місцеве значення
  • Ви анімуєте властивість залежності, поточне значення якої визначено в іншій збірці, яка не об'єднується в словник ресурсів.
  • Ви анімуєте значення, яке наразі пов’язане з даними

1

Пов’язування без INotifyPropertyChanged або DependencyProperties

Як було обговорено тут, ви можете прив’язати звичайну властивість об’єкта CLR без INotifyPropertyChanged, і вона просто працюватиме .

Ось форумчий пост, про який я говорю.

Цитата:

[...] Двигун прив'язки даних WPF буде прив'язувати дані до екземпляра PropertyDescriptor, який обертає властивість джерела, якщо вихідний об'єкт є звичайним об'єктом CLR і не реалізує інтерфейс INotifyPropertyChanged. І двигун прив'язки даних спробує підписатись на подію змінити властивість за допомогою методу PropertyDescriptor.AddValueChanged (). І коли цільовий елемент, пов'язаний з даними, змінить значення властивостей, механізм прив'язки даних викличе метод PropertyDescriptor.SetValue (), щоб перенести змінене значення назад у вихідне властивість, і він одночасно підніме подію ValueChanged, щоб повідомити інших абонентів (у цьому випадку, інші підписники будуть TextBlocks у ListBox.

І якщо ви реалізуєте INotifyPropertyChanged, ви несете повну відповідальність за імплементацію сповіщень про зміни у кожному програмі властивостей, які повинні бути пов'язані з даними інтерфейсу. В іншому випадку зміни не будуть синхронізовані, як ви очікували. [...]

Ось ще одна чудова та детальна стаття на цю тему.

Зверніть увагу, це працює лише при використанні прив'язки . Якщо ви оновите значення з коду , про зміну не надійде сповіщення . [...]

Впровадження INotifyPropertyChanged може бути неабиякою копіткою роботою з розробки. Однак вам потрібно зважити цю роботу на тлі часу виконання (пам'яті та процесора) вашої програми WPF. Реалізація INPC самостійно заощадить процесор виконання та пам'ять .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.