我有一个 WPF 4 DataGrid,其中第一个 ComboBox 通过使用 DataTemplateSelector 键控一个 id 来更改第二个 ComboBox 绑定的内容。出于某种奇怪的原因,第二列中的任何相同类型的单元格似乎都绑定到相同的值。我相信这与使用 DataTemplate 有关,因为我以前见过这个问题,但显然我不了解我需要知道的东西。
这是我到目前为止组装的代码:
MainWindow.xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1" Title="MainWindow" Height="300" Width="300" Loaded="WindowLoaded">
<Window.Resources>
<CollectionViewSource x:Key="MainSource" />
<CollectionViewSource x:Key="TypeSource" />
<CollectionViewSource x:Key="DaysInMonthSource" />
<CollectionViewSource x:Key="DaysInWeekSource" />
<local:TypeSelector x:Key="cbTypeSelector">
<local:TypeSelector.EmptyTemplate>
<DataTemplate x:Name="Emptied">
<Grid></Grid>
</DataTemplate>
</local:TypeSelector.EmptyTemplate>
<local:TypeSelector.DaysInWeekTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding Path=dayNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"
ItemsSource="{Binding Source={StaticResource DaysInWeekSource}}"
DisplayMemberPath="name" SelectedValuePath="id" Name="cb" Padding="3,2,3,3" />
</DataTemplate>
</local:TypeSelector.DaysInWeekTemplate>
<local:TypeSelector.DaysInMonthTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding Path=dayNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"
ItemsSource="{Binding Source={StaticResource DaysInMonthSource}}"
DisplayMemberPath="name" SelectedValuePath="id" Name="cb" Padding="3,2,3,3" />
</DataTemplate>
</local:TypeSelector.DaysInMonthTemplate>
</local:TypeSelector>
</Window.Resources>
<Grid>
<DataGrid AutoGenerateColumns="False" Name="DataGrid1" CanUserAddRows="True" SelectionMode="Single"
EnableColumnVirtualization="True" EnableRowVirtualization="True" >
<DataGrid.Columns>
<DataGridComboBoxColumn
Header="Type" IsReadOnly="False"
DisplayMemberPath="name" SelectedValuePath="id" SelectedValueBinding="{Binding Path=type_id, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"
ItemsSource="{Binding Source={StaticResource TypeSource}}">
</DataGridComboBoxColumn>
<DataGridTemplateColumn Header="Day" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentPresenter local:Helper.UpdateTrigger="{Binding Path=type_id}" ContentTemplateSelector="{StaticResource cbTypeSelector}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
主窗口.xaml.cs
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace WpfApplication1
{
public class DayContainer
{
public int id { get; set; }
public string type_id { get; set; }
public string dayNumber { get; set; }
}
public class TypeSelector : DataTemplateSelector
{
public DataTemplate EmptyTemplate { get; set; }
public DataTemplate DaysInWeekTemplate { get; set; }
public DataTemplate DaysInMonthTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var element = container as FrameworkElement;
if (element == null || item == null) return EmptyTemplate;
var dgr = FindVisualParent<DataGridRow>(element);
var drv = dgr.Item as DayContainer;
if (drv == null) return EmptyTemplate;
if (drv.type_id == "1")
return DaysInWeekTemplate;
if (drv.type_id == "2")
return DaysInMonthTemplate;
return EmptyTemplate;
}
public static T FindVisualParent<T>(UIElement element) where T : UIElement
{
var parent = element;
while (parent != null)
{
var correctlyTyped = parent as T;
if (correctlyTyped != null) return correctlyTyped;
parent = VisualTreeHelper.GetParent(parent) as UIElement;
}
return null;
}
}
public class Helper
{
public static object GetUpdateTrigger(DependencyObject obj)
{
return obj.GetValue(UpdateTriggerProperty);
}
public static void SetUpdateTrigger(DependencyObject obj, object value)
{
obj.SetValue(UpdateTriggerProperty, value);
}
public static readonly DependencyProperty UpdateTriggerProperty =
DependencyProperty.RegisterAttached("UpdateTrigger", typeof(object), typeof(Helper), new FrameworkPropertyMetadata(OnUpdateTriggerChanged));
public static void OnUpdateTriggerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var cp = d as ContentPresenter;
if (cp == null) return;
var temp = cp.Content;
cp.Content = null;
cp.Content = temp;
}
}
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
var source = (CollectionViewSource)FindResource("MainSource");
source.Source = new List<DayContainer>
{
new DayContainer {id = 1, type_id = "1", dayNumber = "1"},
new DayContainer {id = 2, type_id = "1", dayNumber = "2"},
new DayContainer {id = 3, type_id = "2", dayNumber = "3"},
};
DataGrid1.ItemsSource = source.View;
source = (CollectionViewSource)FindResource("TypeSource");
if (source != null && source.Source == null)
source.Source
= new[]
{
new {id = "1", name = "Week"},
new {id = "2", name = "Month"}
};
source = (CollectionViewSource)FindResource("DaysInWeekSource");
if (source != null && source.Source == null)
source.Source
= new[]
{
new {id = "1", name = "Sunday"},
new {id = "2", name = "Monday"},
new {id = "3", name = "Tuesdsay"},
new {id = "4", name = "Wedsnesday"},
new {id = "5", name = "Thursday"},
new {id = "6", name = "Friday"},
new {id = "7", name = "Saturday"}
};
source = (CollectionViewSource)FindResource("DaysInMonthSource");
if (source != null && source.Source == null)
source.Source = from n in Enumerable.Range(1, 31)
select new { id = n.ToString(CultureInfo.InvariantCulture), name = n.ToString(CultureInfo.InvariantCulture) };
}
}
}