Родственная привязка Silverlight ItemTemplate ListboxItem - Список - PullRequest
1 голос
/ 02 февраля 2010

Я программно создал класс (я назвал его ViewGrid), чтобы использовать его экземпляр в качестве ItemTemplate для своего элемента управления ListBox; конечно, это мой шаблон данных для listboxitem ....

Кроме того, в моем классе ViewGrid я получил свойство зависимости с именем IsChecked и хочу синхронизировать его со свойством ListBoxItem IsSelected. Я заметил, что в SL нет поддержки родственников source-findancestor-ancestortype для связывания, как в WPF, но мне нужно найти способ синхронизировать мое свойство IsChecked со свойством IsSelected внутренне сгенерированного ListBoxItem для моего Элемент управления ListBox. Вы можете помочь?

Ответы [ 2 ]

0 голосов
/ 27 января 2017

ОБНОВЛЕНИЕ: я пересмотрел это и нашел намного лучшее решение. Мой оригинальный остается ниже, но способ, которым я фактически решил эту проблему, заключается в использовании ViewGrid в ControlTemplate вместо DataTemplate. Затем вы можете использовать привязку RelativeSource TemplatedParent для привязки к свойству IsSelected объекта ListBox. Итак, добавьте следующее в Ресурсы списка или на свою страницу или пользовательский элемент управления:

<Style TargetType="ListBoxItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <StackPanel>
                    <ViewGrid IsChecked="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"/>​
                    <!-- other controls may go here -->
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

ОРИГИНАЛ:

Итак, через семь лет вам почти наверняка не понадобится ответ на этот вопрос ... однако я недавно провел утреннюю борьбу с этим вопросом и подумал, что я дам свое решение на случай, если какое-нибудь подобное несчастье закончится здесь .

Во-первых, всем, кто использует Silverlight 5, повезло, так как AncestorType, очевидно, теперь доступен для RelativeSource, что позволяет вам напрямую связываться со свойством IsSelected объекта ListBoxItem. Для тех из нас, кто придерживался 4 или ниже, единственный реальный обходной путь, который я нашел, это «подделка» привязки с помощью событий в коде.

Для этого предположим, что у вас есть XAML-файл YourView с ListBox с именем «lbYourListBox», свойства которого ItemsSource и SelectedItem которого связаны с соответствующими свойствами класса YourViewModel, а также ViewGrid в его ItemTemplate, свойство IsChecked которого не связано с что-нибудь. Затем в своем файле кода вы связываете события следующим образом:

public YourView()
    {
        InitializeComponent();
        this.Loaded += (sender, e) =>
        {
            ((YourViewModel)this.DataContext).PropertyChanged += vm_PropertyChanged;
            UpdateViewGrids();
        };

    }

    // this part propagates changes from the view to the view model
    private void viewGrid_Checked(object sender, RoutedEventArgs e)
    {
        var selectedVM = ((ViewGrid)sender).DataContext as SourceItemType;
        ((YourViewModel)this.DataContext).SelectedViewGridItem = selectedVM;
    }

    private void vm_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (string.Equals(e.PropertyName, "SelectedViewGridItem"))
        {
            UpdateViewGrids();
        }
    }

    // this part propagates changes from the view model to the view
    private void UpdateViewGrids()
    {
        var viewGrids = this.lbYourListBox.GetVisualDescendants().OfType<ViewGrid>();
        var selectedVM = ((YourViewModel)this.DataContext).SelectedViewGridItem;
        foreach (var grid in viewGrids)
        {
            grid.IsChecked = selectedVM == grid.DataContext;
        }
    }​

Обработчик события viewGrid_Checked должен быть связан с событием Checked сетки представления в ItemTemplate. Метод GetVisualDescendants () происходит из набора инструментов Silverlight.

Важные замечания:

  • Событие ViewGrid.Checked не должно запускаться, за исключением перехода unchecked-> selected, и одновременно должна быть выбрана не более одной сетки вида. Если эти две вещи не соответствуют действительности, вам придется внести соответствующие изменения, чтобы этот код не мог вызвать бесконечный цикл, управляемый событиями. (Конечно, если вам не нужна двусторонняя привязка, вам нужен только один из этих обработчиков событий, и пинг-понг событий не представляет проблемы.)
  • Я написал это для пользовательского элемента управления, у которого контекст данных был установлен в XAML, поэтому обработчик события для события PropertyChanged модели представления назначается только после загрузки представления. В зависимости от того, как и когда ваш вид и модель вида связаны друг с другом, вам может потребоваться назначить это раньше / позже / по-разному.
  • Это не будет работать, если сетки вида не видны, а GetVisualDescendants, похоже, игнорирует скрытые / свернутые элементы управления.
0 голосов
/ 03 февраля 2010

Вот ListBox, определенный в XAML, который использует свойство IsSelected каждого LitBoxItem, чтобы показать или скрыть кнопку при выборе. Вам просто нужно продублировать этот подход Binding для ListBoxItems, который вы создаете в коде. Либо так, либо создайте UserControl с соответствующим XAML ListBoxItem и вставьте экземпляры этих UserControls в свой ListBox.

<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Width="200" Height="120">
                <StackPanel Margin="5">
                    <TextBlock Text="{Binding Name, Mode=OneWay}" />
                    <StackPanel Visibility="{Binding IsSelected, Mode=OneWay, Converter={StaticResource BoolToVisible}}">
                        <Button Content="Show Details" Click="OnDetailsClick" Tag="{Binding}" />
                    </StackPanel>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Удачи,

Джим МакКарди

Программное обеспечение Face To Face и YinYangMoney

...