【发布时间】:2011-11-16 21:11:08
【问题描述】:
我遇到了似乎无法解决的数据绑定问题。 (警告:下面的完整代码示例)
我正在开发一个能够将不同项目分组到命名组中的分组控件。我有一个数据模型,它定义了这个设置,它有一个 observablecollection 组,每个组都有一个 observablecollection 项目:
public class GroupingModel
{
public ObservableCollection<Group> Groups { get; set; }
public GroupingModel()
{
Groups = new ObservableCollection<Group>();
}
public void RegroupItem(Item item)
{
var containingGroup = Groups.FirstOrDefault(x => x.Items.Contains(item));
if (containingGroup == null ||
item.GroupName == containingGroup.GroupName)
return;
containingGroup.Items.Remove(item);
var newGroup = Groups.FirstOrDefault(x => x.GroupName == item.GroupName);
if (newGroup == null)
{
newGroup = new Group()
{
GroupName = item.GroupName
};
newGroup.Items.Add(item);
Groups.Add(newGroup);
}
else
{
newGroup.Items.Add(item);
}
}
}
public class Group
{
public ObservableCollection<Item> Items { get; set; }
public string GroupName { get; set; }
public Group()
{
Items = new ObservableCollection<Item>();
}
}
public class Item
{
public string GroupName { get; set; }
public string Title { get; set; }
public object Content { get; set; }
}
此数据模型已填充并绑定到 DataContext:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
SetupModel();
}
private GroupingModel m_model = new GroupingModel();
private void SetupModel()
{
var group = new Group()
{
GroupName = "Default",
};
for (int i = 0; i < 5; i++)
{
Item item = new Item()
{
Title = "Item " + i,
GroupName = "Default",
Content = new TextBlock
{
Text = "Hello: " + i,
}
};
group.Items.Add(item);
}
m_model.Groups.Add(group);
DataContext = m_model;
}
private void movegroup(object sender, RoutedEventArgs e)
{
var firstGroup = m_model.Groups.First();
var item = firstGroup.Items.FirstOrDefault();
if (item != null)
{
item.GroupName = "NewGroup";
m_model.RegroupItem(item);
}
}
}
最后我在 XAML 中绑定了整个东西,如下所示:
<UserControl x:Class="ObservableCollectionBinding.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit" >
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Content="Move first to new group" Click="movegroup" />
<ItemsControl ItemsSource="{Binding Groups}" Grid.Row="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock FontWeight="ExtraBlack" Text="{Binding GroupName}" Margin="0,2,0,2" />
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<toolkit:Expander Header="{Binding Title}" Content="{Binding Title}">
<!--Content="{Binding Content}"-->
</toolkit:Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
按下按钮时,我通过从可观察项目集合中删除、创建新组、将项目插入该组并将新组添加到可观察组集合中来将默认组中的第一项移动到新组中.当 Expander 中的 Content 属性绑定到 Title 属性时,这可以正常工作。您可以展开和关闭项目并将它们全部移动到新组中。
但是,如果我将其更改为绑定到 Content 属性(上面注释掉的行,它绑定到在代码隐藏中创建的 TextBlock),则绑定可以很好地开始(扩展器可以打开和关闭,TextBlock 是如图所示),但如果您尝试移动已展开的项目,应用程序会因 ArgumentException 和消息“值不在预期范围内”而终止。
我是否正在尝试做一些不受支持的事情(将内容绑定到在代码隐藏中创建的用户控件),我是否设置了不正确的绑定或其他错误。
注意:我真的希望绑定能够与在代码隐藏中创建的用户控件一起使用,因为为我们的特定用户控件创建完整的数据绑定模型将是一项相当大的工作。
【问题讨论】:
标签: silverlight data-binding user-controls observablecollection