Неподеленное поведение WPF
У меня есть две DataGrids в Window, и я использую поведение Blend для создания фильтров в заголовках столбцов.
<DataGrid>
<i:Interaction.Behaviors>
<v:ColumnBehavior/>
</i:Interaction.Behaviors>
</DataGrid>
<DataGrid>
<i:Interaction.Behaviors>
<v:ColumnBehavior/>
</i:Interaction.Behaviors>
</DataGrid>
Проблема в том, что экземпляр этого поведения так или иначе является общим для обеих DataGrids, поэтому, если вы установите фильтр для первой DataGrid, он будет установлен автоматически во второй DataGrid и наоборот. Мне нужно, чтобы эти фильтры (поведения) были независимыми. Из того, что я прочитал, невозможно добиться стилями.
Класс поведения:
Imports System.ComponentModel
Imports System.ComponentModel.DataAnnotations
Imports System.IO
Imports System.Text
Imports System.Windows.Controls.Primitives
Imports System.Windows.Interactivity
Imports System.Windows.Markup
Namespace View
Friend Class ColumnBehavior
Inherits Behavior(Of DataGrid)
Protected Overrides Sub OnAttached()
MyBase.OnAttached()
AddHandler AssociatedObject.AutoGeneratingColumn, AddressOf OnAutoGeneratingColumn
End Sub
Protected Sub OnAutoGeneratingColumn(sender As Object, e As DataGridAutoGeneratingColumnEventArgs)
If e.PropertyDescriptor IsNot Nothing Then
Dim descriptor = DirectCast(e.PropertyDescriptor, PropertyDescriptor)
Dim customString = DirectCast(descriptor.Attributes(GetType(CustomStringAttribute)), CustomStringAttribute)
If customString IsNot Nothing Then
Dim unitType = DirectCast([Enum].Parse(GetType(DataGridLengthUnitType), customString.Value), DataGridLengthUnitType)
e.Column.Width = New DataGridLength(1, unitType)
End If
Dim display = DirectCast(descriptor.Attributes(GetType(DisplayAttribute)), DisplayAttribute)
If display IsNot Nothing Then
e.Cancel = (Not display.GetAutoGenerateField().GetValueOrDefault(True))
e.Column.Header = display.GetShortName()
Dim headerStyle = e.Column.HeaderStyle
If headerStyle Is Nothing Then headerStyle = New Style(GetType(DataGridColumnHeader))
headerStyle.Setters.Add(New Setter(ToolTipService.ToolTipProperty, display.GetDescription()))
e.Column.HeaderStyle = headerStyle
If display.GetAutoGenerateFilter().GetValueOrDefault(False) Then
Dim comboBoxBinding = DirectCast(descriptor.Attributes(GetType(ComboBoxBindingAttribute)), ComboBoxBindingAttribute)
If comboBoxBinding IsNot Nothing Then
Dim bindingString = "{{Binding {0}, RelativeSource={{RelativeSource FindAncestor, AncestorType={{x:Type Window}}}}}}"
Dim dataTemplateXaml = <DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Margin="0,0,4,0"
VerticalAlignment="Center"
Grid.Column="0"/>
<ComboBox
IsReadOnly="True"
ItemsSource=<%= String.Format(bindingString, comboBoxBinding.ItemsSource) %>
SelectedItem=<%= String.Format(bindingString, comboBoxBinding.SelectedItem) %>
Grid.Column="1"
SelectedIndex="0"/>
</Grid>
</DataTemplate>
Dim headerTemplate As DataTemplate
Using dataTemplateReader As New MemoryStream(Encoding.UTF8.GetBytes(dataTemplateXaml.ToString()))
Dim context As New ParserContext
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation")
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml")
headerTemplate = DirectCast(XamlReader.Load(dataTemplateReader, context), DataTemplate)
End Using
e.Column.HeaderTemplate = headerTemplate
End If
End If
End If
Dim displayFormat = DirectCast(descriptor.Attributes(GetType(DisplayFormatAttribute)), DisplayFormatAttribute)
If displayFormat IsNot Nothing Then
DirectCast(e.Column, DataGridBoundColumn).Binding.StringFormat = displayFormat.DataFormatString
End If
End If
End Sub
Protected Overrides Sub OnDetaching()
MyBase.OnDetaching()
RemoveHandler AssociatedObject.AutoGeneratingColumn, AddressOf OnAutoGeneratingColumn
End Sub
End Class
End Namespace
Атрибуты в модели используются для автоматического создания фильтров в DataGrid:
<Display(ShortName:="Meeting", Description:="Meeting code", AutoGenerateField:=True, AutoGenerateFilter:=True)>
<ComboBoxBinding("DataContext.MeetingCodes", "DataContext.TasksMeetingCodeFilter")>
<CustomString("SizeToCells")>
Public Property TaskMeetingCode As String Implements ITaskView.TaskMeetingCode
1 ответ
Проблема решена. Есть два экземпляра класса поведения, как и должно быть, но оба экземпляра привязаны к одному и тому же свойству в viewmodel...