Рейтинг@Mail.ru

Запрет выделения элементов ListBox / ListView (WPF)

Published in Полезные советы

Чтобы запретить выделение элементов элемента ListBox или ListView, можно определить это с помощью такого стиля:

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
         <Setter Property="Focusable" Value="False" />
    </Style>
</ListBox.ItemContainerStyle>

Второй вариант – использовать вместо ListBox элемент ItemsControl.

Читать далее...

Как определить текущую привязку Binding элемента UI

Published in Полезные советы

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

    Dim be As BindingExpression = myTextBlock.GetBindingExpression(TextBlock.TextProperty)
    Dim bnd As Binding = be.ParentBinding
    Dim bindingPath As String = bnd.Path.Path
Читать далее...

Аналог StartupPath в WPF

Published in Полезные советы

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

    Dim startup As String = Application.StartupPath

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

    Dim startup As String = System.AppDomain.CurrentDomain.BaseDirectory
Читать далее...

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

Published in Полезные советы

В .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 можно добавить методы для удаления, вставки или перемещения набора элементов коллекции.

Читать далее...

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

Published in Полезные советы

Допустим, вы пишете приложение 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

Published in Полезные советы

Как сделать привязку (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 сделать привязку к значению системной переменной

Published in Полезные советы

Допустим, мы хотим прямо в 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}" />
Читать далее...
Subscribe to this RSS feed