Привязка данных Silverlight, наблюдаемые коллекции и пользовательский контроль - PullRequest
0 голосов
/ 14 сентября 2011

Я столкнулся с проблемой привязки данных, которую не могу решить.(Предупреждение: полный пример кода ниже)

Я разрабатываю элемент управления группированием, который может группировать различные элементы в именованные группы.У меня есть модель данных, которая определяет эту настройку, которая имеет наблюдаемую коллекцию групп, и у каждой группы есть наблюдаемая коллекция элементов:

  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 было бы довольно сложным занятием.

1 Ответ

0 голосов
/ 10 июля 2012

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

Итак, я думаю, что приму это как ответ при отсутствии чего-то лучшего

...