Я столкнулся с проблемой привязки данных, которую не могу решить.(Предупреждение: полный пример кода ниже)
Я разрабатываю элемент управления группированием, который может группировать различные элементы в именованные группы.У меня есть модель данных, которая определяет эту настройку, которая имеет наблюдаемую коллекцию групп, и у каждой группы есть наблюдаемая коллекция элементов:
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>
При нажатии кнопки я перемещаю первый элемент из группы по умолчанию в новую группу, удаляя из коллекции наблюдаемых элементов, создаваяновая группа, вставка элемента в эту группу и добавление новой группы в наблюдаемую коллекцию групп.Это работает правильно, когда свойство Content в Expander связано со свойством Title.Вы можете раскрывать и закрывать элементы и перемещать их все в новую группу.
Однако, если я изменю это, чтобы привязать к свойству Content (закомментированная выше строка, которая привязывается к TextBlock, созданному в codebehind).) привязка отлично работает для начала (расширители могут открываться и закрываться, отображается TextBlock), но если вы попытаетесь переместить элемент, который был развернут, приложение умирает с ArgumentException и сообщением 'Valueне попадает в ожидаемый диапазон ».
Пытаюсь ли я сделать что-то, что не поддерживается (привязка содержимого к пользовательскому контролю, созданному в codebehind), неправильно настроил привязку или что-то еще не так.
ПРИМЕЧАНИЕ. Я действительно надеюсь получить привязку для работы с usercontrol, созданным в codebehind, поскольку создание полной модели привязки данных для нашего конкретного usercontrol было бы довольно сложным занятием.