【问题标题】:Silverlight relativebinding ItemTemplate ListboxItem - ListboxSilverlight relativebinding ItemTemplate ListboxItem - 列表框
【发布时间】:2011-01-12 03:03:56
【问题描述】:

我以编程方式创建了一个类(我称之为 ViewGrid),以便我将它的一个实例用作我的 ListBox 控件的 ItemTemplate;当然,这是我的 listboxitem 数据模板......

另外,在我的 ViewGrid 类中,我有一个名为 IsChecked 的依赖项属性,我希望它与 ListBoxItem 的 IsSelected 属性保持同步。我注意到在 SL 中没有像 WPF 中那样对绑定的 relativesource-findancestor-ancestortype 支持,但我仍然需要找到一种方法来保持我的 IsChecked 属性与内部生成的 ListBoxItem 的 IsSelected 属性同步我的列表框控件。你能帮忙吗?

【问题讨论】:

  • 您能否提供有关您的 ViewGrid 类的更多详细信息,它是从什么派生的?它是模板控件还是 UserControl?
  • 我使用 Grid 作为它的基类。

标签: silverlight data-binding listbox listboxitem


【解决方案1】:

这是在 XAML 中定义的 ListBox,它使用每个 LitBoxItem 的 IsSelected 属性在选中时显示或隐藏按钮。您只需为您在代码中创建的 ListBoxItems 复制该绑定方法。要么这样,要么使用适当的 ListBoxItem XAML 创建一个 UserControl,然后将这些 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 SoftwareYinYangMoney

【讨论】:

  • 我没有在我的代码中创建 ListBoxItems,我只是使用一个集合作为我的列表框的源,所以列表框项是由框架生成的。我相信这个“​​{Binding IsSelected...”绑定指向数据项的属性而不是我的可视化树(ViewGrid)实例?...
【解决方案2】:

更新:我重新审视了这个并找到了一个更好的解决方案。我原来的那个还在下面,但我最终解决这个问题的方法是通过在 ControlTemplate 中使用 ViewGrid 而不是 DataTemplate。然后可以使用RelativeSource TemplatedParent 绑定绑定到ListBox 的IsSelected 属性。因此,将以下内容添加到列表框或页面或用户控件的资源中:

<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,让您可以直接绑定到 ListBoxItem 的 IsSelected 属性。对于我们这些坚持 4 或以下的人来说,我想出的唯一真正的解决方法是通过使用背后代码中的事件来“伪造”绑定。

为此,假设您的 YourView XAML 带有一个名为“lbYourListBox”的 ListBox,它的 ItemsSource 和 SelectedItem 属性绑定到 YourViewModel 类的适当属性,以及其 ItemTemplate 中的 ViewGrid,其 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 事件处理程序应该连接到 ItemTemplate 中视图网格的 Checked 事件。 GetVisualDescendants() 方法来自 Silverlight 工具包。

重要提示:

  • ViewGrid.Checked 事件不应触发,除非是 unchecked->checked 转换,并且一次只能选择一个视图网格。如果这两件事不正确,则必须进行适当的编辑以确保此代码不会导致无限的事件驱动循环。 (当然,如果您不需要双向绑定,则只需要其中一个事件处理程序,事件 ping-pong 不是问题。)
  • 我为在 XAML 中设置了数据上下文的用户控件编写了此代码,这就是视图模型的 PropertyChanged 事件的事件处理程序仅在视图加载后分配的原因。根据您的视图和视图模型相互绑定的方式和时间,您可能需要更早/更晚/不同地分配它。
  • 如果视图网格不可见,这将不起作用,GetVisualDescendants 似乎会忽略隐藏/折叠的控件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    相关资源
    最近更新 更多