Рейтинг@Mail.ru

Аналог StartupPath в WPF

Опубликовано в Полезные советы

В приложениях Windows Forms была возможность определить каталог, из которого запускалось приложение, так:

    Dim startup As String = Application.StartupPath

В WPF данная возможность не работает. Теперь для определения текущей директории приложения нужно вызвать следующий код:

    Dim startup As String = System.AppDomain.CurrentDomain.BaseDirectory
Подробнее ...

Observable collection с уведомлением при добавлении диапазона значений

Опубликовано в Полезные советы

В .NET есть такой перечислимый тип как ObservableCollection. Его особенность в том, что эта коллекция при изменении её элементов (добавлении или удалении), уведомляет наблюдающие за ней классы об этом изменении. Это бывает полезно, например, когда к данной коллекции привязаны элементы пользовательского интерфейса. Но если необходимо добавить в коллекцию сразу множество элементов, то добавление каждого элемента будет уведомлять об изменении коллекции каждый раз. Это вызовет избыточную нагрузку на пользовательский интерфейс, и он может даже зависнуть на какое-то время. Чтобы этого избежать, можно написать свой собственный класс, который будет наследовать от ObservableCollection и содержать метод добавления множества элементов за один раз, а уведомлять об этом единожды. Вот как например это можно сделать:

Imports System.Collections.Specialized

''' <summary>
''' ObservableCollection с поддержой добавления множества элементов.
''' </summary>
Public Class ObservableRangeCollection(Of T)
    Inherits ObjectModel.ObservableCollection(Of T)

#Region "CTORs"

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(collection As IEnumerable(Of T))
        MyBase.New(collection)
    End Sub

#End Region '/CTORs

#Region "METHODS"

    ''' <summary>
    ''' Добавляет в коллекцию несколько элементов и в конце уведомляет об этом.
    ''' </summary>
    Public Sub AddRange(collection As IEnumerable(Of T))
        For Each item As T In collection
            Items.Add(item)
        Next
        OnCollectionChanged(New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection))
    End Sub

#End Region '/METHODS

End Class

По аналогии с методом AddRange можно добавить методы для удаления, вставки или перемещения набора элементов коллекции.

Подробнее ...

Форматирование текста с привязкой в XAML

Опубликовано в Полезные советы

Язык разметки XAML поддерживает форматирование, как и сама платформа .NET. Например, этот код фоматирует числовое значение как число с плавающей точкой с 3 знаками после запятой

<TextBlock Text="{Binding NumericValue, StringFormat=F3}" />

Вот так можно отформатировать простой текст:

<TextBlock Text="{Binding Title, StringFormat={}Название: {0}}"/>

Пустые фигурные скобки в начале строки форматирования подсказывают парсеру XAML, что далее в тексте будут встречаться символы подстановки. Можно, кстати, использовать привязку сразу к нескольким переменным, например так:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding StringFormat="{} Его зовут {0} {1}">
            <Binding Path="Name" />
            <Binding Path="Surname" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

А этот код форматирует дату и время с точностью до миллисекунд:

<TextBlock Text="{Binding Value, StringFormat={}{YYYY-MM-dd, HH-mm-ss.FFF}}" />

А вот так можно отформатировать в текущей культуре приложения цену с указанием валюты:

<TextBlock Text="{Binding Path=Price, StringFormat=c}"/>
Подробнее ...

Как изменить языковые настройки на уровне приложения WPF

Опубликовано в Полезные советы

Допустим, вы пишете приложение WPF. И при обработке строк часто бывает задача преобразования строки в число с плавающей запятой. В русском языке разделитель целой и дробной части – запятая, а в других языках (например, английском) – точка. И вы не хотите каждый раз задавать настройки культуры в этом и других случаях, которые требуют определения текущей культуры. В таком случае можно в файле Application.xaml определить функцию, которая выполняется при загрузке приложения:

<Application x:Class="Application"
    Startup="Application_Startup"
    ...>

Далее в застраничном коде Application.xaml.vb или Application.xaml.cs задаём для текущего потока новые языковые настройки таким способом:

Class Application

    Private Sub Application_Startup(sender As Object, e As StartupEventArgs)
        Thread.CurrentThread.CurrentCulture = New Globalization.CultureInfo("en-US")
    End Sub
	
End Class    

Теперь для всего приложения действует культура en-US, и все строки типа "3,14" и других будут корректно преобразовываться в числа. Это же проявится и во всех остальных случаях: форматирование даты и времени, валюты и прочих, где проявляются культурные особенности того или иного языка.

Подробнее ...

Множественная привязка в WPF

Опубликовано в Полезные советы

Как сделать привязку (binding) визуального элемента в WPF к нескольким свойствам? Для этого существует так назваемая множественная привязка. Вот пример разметки, который использует свойства FirstName и LastName некоторого объекта для вывода их посредством одного элемента TextBlock:

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

Формат вывода текста определяется атрибутом StringFormat. Обратите внимание на пустые фигурные скобки в начале определения формата строки. Они подсказывают парсеру XAML, что здесь используется привязка.

Добиться подобного же результата можно также с помощью конвертера MultiValueConverter, который принимает несколько значений. Вот тот же пример, но с использованием конвертера. Сначала необходимо написать класс самого конвертера:

Public Class PersonNameMultiConverter
    Implements IMultiValueConverter

        Public Function Convert(values() As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IMultiValueConverter.Convert
            If (values.Length > 0) Then
                Dim firstName As String = values(0).ToString()
                Dim lastName As String = values(1).ToString()
                Return firstName & " " & lastName
            End If
            Return String.Empty
        End Function

        Public Function ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
            Throw New NotImplementedException()
        End Function
End Class

Далее в начале XAML файла, в котором планируется использовать данный конвертер, в разделе ресурсов необходимо объявить соответствующий ресурс:

<conv:PersonNameMultiConverter x:Key="personNameMultiConverter" />

И далее создадим текстовое поле и добавим ему привязку:

<TextBlock>
  <TextBlock.Text>
    <MultiBinding Converter="{StaticResource personNameMultiConverter}">
      <Binding Path="FirstName" />
      <Binding Path="LastName" />
    </MultiBinding>
  </TextBlock.Text>
</TextBlock>

Гораздо больше кода потребовалось, чем в первом варианте, верно? Однако преимуществом последнего метода является то, что конвертеру можно передавать сложные объекты и производить с ними какую-либо серьёзную обработку, что попросту невозможно при использовании первого варианта.

Подробнее ...

Как в XAML сделать привязку к значению системной переменной

Опубликовано в Полезные советы

Допустим, мы хотим прямо в XAML сделать привязку непосредственно к системной переменной. Скажем, вывести в элементе TextBlock максимальное значение для типа System.UInt64 (беззнаковое 64-разрядное целое). Для этого необходимо:

  1. В начале страницы/окна добавить ссылку на пространство имён System:
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
  2. В XAML коде страницы ссылка на тип будет иметь следующий вид:
    <TextBlock Text="{x:Static Member=sys:UInt64.MaxValue}" />
    или проще:
    <TextBlock Text="{x:Static sys:UInt64.MaxValue}" />
Подробнее ...

Установка масштаба 100% в редакторе XAML

Опубликовано в Полезные советы

В Visual Studio в визуальном редакторе XAML, вплоть до новейшей версии 2019 года, когда открываешь проект и загружаешь интерфейс окна, страницы или пользовательского элемента управления, среда выводит его порой в совершенно неудобном масштабе. Так, например, создаваемое окно в редакторе XAML может отобразиться в масштабе 600% или, наоборот, в масштабе 10% от оригинального. Приходится использовать маленькое выпадающее меню в углу, в котором можно задать масштаб. Да, при повторной загрузке этого окна, Visual Studio запомнит выбранный пользователем масштаб и будет использовать его. Но при выгрузке проекта и повторной загрузке данная информация не сохраняется Придётся снова вручную задавать масштаб. Это долго и неудобно.

Подробнее ...

Определение константы в XAML

Опубликовано в Полезные советы

Можно определить константу заданного типа прямо в XAML, а не в коде. Для этого следует в разделе импорта пространств имён сослаться, среди прочих, на пространство имён System:

xmlns:sys="clr-namespace:System;assembly=mscorlib"

Далее в разделе ресурсов следует объявить константу необходимого типа. Например, для определения строковой константы:

<sys:String x:Key="myConst">Это константа, определённая в  XAML</sys:String>

Аналогичным образом можно объявить даже массив:

<x:Array Type="{x:Type sys:Int32}" x:Key="myIntegerArray">
    <sys:Int32>1</sys:Int32>
    <sys:Int32>2</sys:Int32>
    <sys:Int32>3</sys:Int32>
    <sys:Int32>4</sys:Int32>
</x:Array>

Теперь, в XAML коде страницы или окна, можно использовать определённую константу так:

<TextBlock Text="{StaticResource myConst}" />

Или так:

<ComboBox ItemsSource="{StaticResource myIntegerArray}" />
Подробнее ...
Подписаться на этот канал RSS