Рейтинг@Mail.ru

WPF: Как использовать свойство объекта в качестве параметра конвертера IValueConverter.ConverterParameter

Published in Программирование

Допустим, у нас есть объект MyObject со свойствами MyData и MyProperty. Для его отображения в графическом пользовательском интерфейсе, построенном на XAML, мы хотим использовать эти два свойства, преобразовав MyData с помощью IValueConverter, а MyProperty использовать в качестве параметра конвертера ConverterParameter. Реально ли это?

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

WPF: Выделение элемента ListBoxItem и сброс выделения при повторном нажатии

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

Когда режим выделения элементов списка в XAML SelectionMode="Multiple", элемент выделяется по нажатию «мышью», и таким же образом сбрасывается выделение. В режиме Single выделение сбрасывается только при переключении на другой элемент или при удерживании клавиши Ctrl. Но что если нужно нечто среднее: выделение и снятие выделения элемента ListBoxItem по нажатию кнопкой «мыши», но выделение возможно только одного элемента?

Предлагаю такой вариант решения: задать списку ListBox или ListView множественный режим выделения и запрещать выделение более чем одного элемента. Сделаем это так (код на VB.NET):

''' <summary>'
''' Запрещает выделение множества элементов ListViewItem, когда режим выделения – Multiple.'
''' </summary>'
''' <remarks>Реализует поведение снятия выделения по второму клику на элементе, чтобы не нужно было удерживать Ctrl для снятия выделения.</remarks>'
Private Sub forbidSelectionButOne(sender As Object, e As MouseButtonEventArgs)
    Dim lv As ListView = TryCast(sender, ListView)
    If lv IsNot Nothing Then
        If lv.SelectedIndex <> getCausesListViewItemIndex(sender, e) Then
            lv.SelectedIndex = getCausesListViewItemIndex(sender, e)
            e.Handled = True
        End If
        lv.Focus()
    End If
End Sub
''' <summary>'
''' Возвращает индекс элемента списка, который был нажат мышью.'
''' </summary>'
Private Function getCausesListViewItemIndex(ByVal sender As Object, e As RoutedEventArgs) As Integer
    Dim dep As DependencyObject = TryCast(e.OriginalSource, DependencyObject)
    Do While dep IsNot Nothing AndAlso Not TypeOf (dep) Is ListViewItem
        dep = VisualTreeHelper.GetParent(dep)
    Loop
    If dep Is Nothing Then
        Return -1
    Else
        Dim lv As ListView = TryCast(sender, ListView)
        If lv IsNot Nothing Then
            Dim i As Integer = lv.ItemContainerGenerator.IndexFromContainer(dep)
            Return i
        Else
            Return -1
        End If
    End If
End Function
Читать далее...

WPF: Как получить объект из списка ListBox под указателем мыши

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

Это может понадобиться, например, при реализации функциональности DragAndDrop. Напишем метод, возвращающий объект или NULL, если объекта нет:

''' <summary>'
''' Возвращает элемент списка ListBox, находящийся под указателем мыши.'
''' </summary>'
''' <param name="lb">Список.'
''' <param name="p">Позиция курсора. Обычно e.GetPosition(lb), где е type of DragEventArgs.'
Private Function getDataFromListBox(ByVal lb As ListBox, ByVal p As Point) As Object
  Dim element As UIElement = TryCast(lb.InputHitTest(p), UIElement)
  If element IsNot Nothing Then
    Dim data As Object = DependencyProperty.UnsetValue
      Do While data Is DependencyProperty.UnsetValue
        data = lb.ItemContainerGenerator.ItemFromContainer(element)
        If data Is DependencyProperty.UnsetValue Then
          element = CType(VisualTreeHelper.GetParent(element), UIElement)
         End If
       Loop
       If data IsNot DependencyProperty.UnsetValue Then
         Return data
       End If
     End If
   Return Nothing
End Function
Читать далее...

WPF: Как найти визуального родителя заданного элемента UIElement (VB.NET)

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

Для поиска родителя любого UIElement на странице, напишем такой метод:

''' <summary>'
''' Возвращает визуального родителя заданного типа.'
''' </summary>'
''' <param name="child">Элемент, для которого нужно найти визуального родителя.'
''' <typeparam name="T">Тип искомого родителя.'
Public Shared Function FindVisualParent(Of T As DependencyObject)(ByVal child As DependencyObject) As T
    Dim parentObject As DependencyObject = VisualTreeHelper.GetParent(child)
    If (parentObject Is Nothing) Then
        Return CType(Nothing, T)
    End If
    Dim parent As T = TryCast(parentObject, T)
    If (Not parent Is Nothing) Then
        Return parent
    End If
    Return FindVisualParent(Of T)(parentObject)
End Function
Читать далее...

WPF: Как запретить ввод в поле ввода любых символов, кроме целых чисел

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

Добавим в поле ввода TextBox обработчик нажатий клавиатуры:

<TextBox PreviewTextInput="checkIfInputDigits" />

А вот код самого обработчика (VB.NET):

Private Sub checkIfInputDigits(sender As Object, e As TextCompositionEventArgs)
    Dim re As New Regex("^[0-9]+") 'объявим регулярное выражение, которое соответствует непрерывной последовательности чисел от 0 до 9
    e.Handled = Not re.IsMatch(e.Text) 'запрещаем ввод символов.
End Sub
Читать далее...

Анимация изменения цвета фона элемента при наведении мыши в XAML

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

Чтобы создать простейший эффект изменения цвета фона элемента, создадим в разделе статических ресурсов:

<Color x:Key="selectedColor" A="255" R="191" G="191" B="204" />
<Color x:Key="originalColor" A="255" R="230" G="230" B="250" />
<SolidColorBrush x:Key="originalColorBrush" Color="{StaticResource originalColor}" />

Теперь для элемента настроим триггеры:

<Border Background="{StaticResource originalColorBrush}">
  <Border.Triggers>
    <EventTrigger RoutedEvent="Border.MouseEnter">
      <BeginStoryboard>
        <Storyboard>
          <ColorAnimation From="{StaticResource originalColor}" To="{StaticResource selectedColor}" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Duration="0:0:0.5"  />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Border.Triggers>
  …
</Border>
Читать далее...

Эффект тени и размытие элементов в XAML

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

XAML поддерживает множество эффектов. Например, эффект тени:

<StackPanel.Effect>
  <DropShadowEffect Opacity="0.5" RenderingBias="Performance" Direction="315" ShadowDepth="3" BlurRadius="3" />
</StackPanel.Effect>

После добавления эффекта тени возможно размытие (blur) текста и других элементов. Чтобы устранить этот эффект, нужно задать свойство родительского элемента

RenderOptions.BitmapScalingMode="NearestNeighbor"
Читать далее...

Почему ComboBox сбрасывает выбранный элемент SelectedItem при двунаправленной привязке?

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

Почему ComboBox может сбрасывать выбранный элемент SelectedItem при двунаправленной привязке, хотя вроде бы всё сделано верно? Например, есть такая XAML разметка:

<ComboBox SelectedItem="{Binding MySelectedItem, Mode=TwoWay}" ItemsSource="{Binding MyList, Mode=OneWay}" />

Так привязка работать не будет. А вот так будет:

<ComboBox ItemsSource="{Binding MyList, Mode=OneWay}" SelectedItem="{Binding MySelectedItem, Mode=TwoWay}" />

Несмотря на практически идентичную разметку, первый кусок кода работает не так, как ожидается.

Нюанс в том, что парсер XAML-разметки разбирает код последовательно. Если сначала объявлена привязка выделенного элемента SelectedItem, а после – источник данных для ComboBox, то при загрузке окна и построении графического интерфейса GUI всегда будет выбран первый элемент (ComboBox.SelectedIndex=0).

Поэтому следует всегда объявлять сначала источник элементов списка ComboBox.ItemsSource, а потом привязку выделенного элемента ComboBox.SelectedItem. Это касается и других элементов графического интерфейса, источниками которых являются коллекции, списки или массивы.

Читать далее...
Subscribe to this RSS feed