Скрытые возможности 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. Скрытые возможности Perl
  5. Скрытые возможности Java
  6. Скрытые возможности VB.NET
  7. Скрытые возможности PHP
  8. Скрытые возможности Ruby
  9. Скрытые возможности C
  10. И так далее........
Sauron
источник
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
должно быть вики сообщества
tsilb
2
@tsilb Я не думаю, что это должна быть вики сообщества, взгляните на эту ссылку meta.stackexchange.com/questions/392/…
Прашант Чолачагудда

Ответы:

87

Мультибиндинг (в сочетании со StringFormat):

<TextBlock>
  <TextBlock.Text>
    <MultiBinding StringFormat="{}{0}, {1}">
      <Binding Path="LastName" />
      <Binding Path="FirstName" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>
Жюльен Пулен
источник
1
здорово :-), если вы не используете Silverlight 4 или более раннюю версию.
скрестим
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 
idursun
источник
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}'}"
Райан Версо
Полезно знать, я привык просто игнорировать их.
Брайан Андерсон,
1
Я пытался передать, что подойдет любая строка форматирования. Я считаю, что в этом случае интернационализированной версией будет StringFormat = '{} {0: d}'.
Брайан Андерсон
29

Иногда вы получаете строку, которая слишком длинная для отображения на этикетке. В этом случае мы можем использовать TextTrimmingсвойство TextBlockпоказывать эллипсы.

<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 по-прежнему не добавлен. Я что-то упускаю?
Elmo
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, а не в скомпилированных :(
kevindaub
Да, только свободный 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: Arguments.

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

<!-- XAML 2009 -->
<DateTime>
    <x:Arguments>
        <x:Int64>100</x:Int64>
    </x:Arguments>
</DateTime>
Саурон
источник
18

Не совсем скрытая функция, но с WPF / XAML вы получаете Беа Столльниц и Джоша Смита . Королева и король программирования WPF / XAML.

Брайана Андерсона
источник
3
Что такое Карл? Джек? Или Джокер?
cplotts
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 (кстати, он использует GridViewColumnHeader.Clickсобытие, упомянутое Ортусом)

Томас Левеск
источник
Где- WinUtil.EnableAeroGlassнибудь доступен источник ?
Оскар
Да, но он сильно изменился с тех пор, как я опубликовал это ... Теперь есть 2 свойства, EnableBlur и GlassFrameMargins. Вы можете найти код здесь: projets.developpez.com/projects/dvp-net/repository/entry/trunk/…
Thomas Levesque
15

Вы можете ссылаться на вложенные типы в XAML, используя знак плюса ( +). Например, если бы у нас был этот класс:

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

Мы могли бы ссылаться на SomeValueXAML, используя следующий синтаксис:

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

Этот синтаксис не задокументирован в MSDN и официально не поддерживается. Кто-то спросил об этом на форумах MSDN, и, по-видимому, это нарушает конструктор WPF 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

Расширенные свойства заголовка

Еще не очень понятно, что содержимое некоторых свойств, к которым мы привыкли, содержит только текст. Если свойство элемента графического интерфейса относится к типу Object, весьма вероятно, что вы можете, вместо того, чтобы просто устанавливать текст, добавить панель по вашему желанию, которая включает набор элементов управления.

Примером этого является MenuItem, где Headerсвойство (обычно содержащее только текст) может содержать набор элементов графического интерфейса, заключенных в элемент управления панели (или только один элемент графического интерфейса, если вам нужен только один).

Также обратите внимание на 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

Плагин экспорта XAML Blender

Плагин экспорта Lightwave XAML

Экспорт Visio XAML

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

Конвертер Maya в XAML

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

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

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

Саурон
источник
также очень полезно: GridLengthConverter, BooleanToVisibilityConverter, AlternationConverter все в System.Windows.Controls
Maciek Świszczowski
6

Встроенные типы

Если вы хотите добавить объекты простых типов, таких как string или double, в словарь ресурсов сегодня, вам необходимо сопоставить необходимые пространства имен 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/> 
Саурон
источник
Это не работает при использовании WPF для обработки XAML. 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.
Mike Strobel
1
@MikeStrobel: Он работает практически везде, и мне наплевать на то, что дизайнеры ломаются.
HB
6

Использование системных цветов

<Border Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
SeeSharp
источник
3
Указание его как DynamicResource важно, поскольку пользователь может изменять системные цвета во время работы вашего приложения.
М. Дадли
3

Поддержка ключей произвольного словаря

В XAML 2006 все явные значения x: Key обрабатывались как строки. В 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>
Sauron
источник
2

Установить ValidationError по коду

ValidatioRule в 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 (ов) в текстовый блок

Я не знаю, насколько это полезно (хотя это и считается скрытым) ... но оно наверняка застало меня врасплох, когда я впервые столкнулся с ним :

<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, и оно будет работать .

Вот форум, о котором я говорю.

Quote:

[...] Механизм привязки данных WPF будет связывать данные с экземпляром PropertyDescriptor, который обертывает исходное свойство, если исходный объект является простым объектом CLR и не реализует интерфейс INotifyPropertyChanged. И механизм привязки данных попытается подписаться на событие изменения свойства с помощью метода PropertyDescriptor.AddValueChanged (). И когда целевой элемент с привязкой к данным изменяет значения свойств, механизм привязки данных вызывает метод PropertyDescriptor.SetValue () для передачи измененного значения обратно в исходное свойство и одновременно вызывает событие ValueChanged, чтобы уведомить других подписчиков (в данном случае, остальные подписчики будут TextBlocks в ListBox.

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

Вот еще одна отличная и подробная статья на эту тему.

Обратите внимание, что это работает только при использовании привязки . Если вы обновите значения из кода , уведомление об изменении не будет . [...]

Реализация INotifyPropertyChanged может быть довольно утомительной работой по разработке. Однако вам нужно сопоставить эту работу с объемом времени выполнения (память и процессор) вашего приложения WPF. Самостоятельная реализация INPC позволит сэкономить ЦП и память во время выполнения .

оборота UrbanEsc
источник