绑定到ItemsControl中的选定项

时间:2010-01-26 19:27:44

标签: wpf xaml data-binding binding itemscontrol

我创建了一个自定义ComboBox,如下所示:(注意,代码不正确但你应该得到一般的想法。)ComboBox包含2个依赖属性,它们很重要:TitleTextDescriptionText

<Grid>
  <TextBlock x:Name="Title"/>
  <Grid x:Name="CBG">
    <ToggleButton/>
    <ContentPresenter/>
    <Popup/>
  </Grid>
</Grid>

我想使用此ComboBox来显示各种选项。我创建了一个名为Setting的类,它继承自DependencyObject以创建可用的项目,我创建了一个DataTemplate来将此Settings对象的内容绑定到我的ComboBox并创建了一个{ {1}}包含UserControl,其中包含我之前提到的ItemsControl模板。我可以用DataTemplate个对象填充它。

Setting

我希望获得所选<DataTemplate x:Key="myDataTemplate"> <ComboBox TitleText="{Binding Title}" DescriptionText="{Binding DescriptionText}"/> </DataTemplate> <UserControl> <Grid> <StackPanel Grid.Column="0"> <ItemsControl Template="{StaticResource myDataTemplate}"> <Item> <Setting Title="Foo" Description="Bar"> <Option>Yes</Option><Option>No</Option> </Setting> </Item> </ItemsControl> </StackPanel> <StackPanel Grid.Column="1"> <TextBlock x:Name="Description"/> </StackPanel> </Grid> </UserControl> 的{​​{1}}(由DescriptionText控件的ComboBoxIsFocus属性选择popup)放在ComboBox的{​​{1}} IsOpen中。

我设法实现这一目标的一种方法是将Description替换为TextBlock,但这会导致几个问题:即使我禁用了滚动条,它总是显示滚动条,当我的弹出窗口已打开,但只有当我在UserControl中明确选择了该项目时,当我启用ItemsControl属性时,ListBox的内容根本不会显示,我不得不重新开始-theme ListBox控件以匹配我的OverridesDefaultStyle布局......

在不使用ListBox或创建自定义ListBox控件的情况下,让UserControl显示的最佳和最简单方法是什么(因为它与{{1具有相同的效果}})?

最后的目标是遍历所有项目(可能将它们变为DescriptionText或某种类型,并将它们保存到我的设置文件中。

2 个答案:

答案 0 :(得分:1)

我想我知道你要做什么。这是一个可能的解决方案。

您应该使用ListBox(或从Selector控件派生的任何内容)才能使用SelectedItem属性。

<UserControl>
  <Grid>
    <StackPanel Grid.Column="0">
      <ListBox x:Name="SettingListBox" Template="{StaticResource myDataTemplate}">
        <Item>
          <Setting Title="Foo" Description="Bar">
            <Option>Yes</Option><Option>No</Option>
          </Setting>
        </Item>
      </ListBox >
    </StackPanel>
    <StackPanel Grid.Column="1">
      <TextBlock x:Name="Description"
          Text="{Binding SelectedItem.Description, ElementName=SettingListBox}"/>
    </StackPanel>
  </Grid>
</UserControl>

要解决打开ComboBox下拉菜单时ListBox没有关注项目的问题,我有一个附加属性可以为您解决这个问题。

public class ListBoxHelper
{
    #region Dependency Property

    public static bool GetCanFocusParent(DependencyObject obj)
    {
        return (bool)obj.GetValue(CanFocusParentProperty);
    }

    public static void SetCanFocusParent(DependencyObject obj, bool value)
    {
        obj.SetValue(CanFocusParentProperty, value);
    }

    // Using a DependencyProperty as the backing store for CanFocusParent.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CanFocusParentProperty =
        DependencyProperty.RegisterAttached("CanFocusParent", typeof(bool), typeof(ListBoxHelper), new UIPropertyMetadata(false, OnCanFocusParentChanged));



    #endregion

    private static void OnCanFocusParentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        var element = obj as UIElement;
        if(element == null) return;

        if((bool)args.NewValue)
            element.PreviewMouseDown += FocusOnParent;
        else
            element.PreviewMouseDown -= FocusOnParent;
    }

    private static void FocusOnParent(object sender, RoutedEventArgs e)
    {
        var listBoxItem = VisualUpwardSearch<ListBoxItem>(sender as DependencyObject) as ListBoxItem;
        if (listBoxItem != null) listBoxItem.IsSelected = true;
    }

    public static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
    {
        while (source != null && source.GetType() != typeof(T))
            source = VisualTreeHelper.GetParent(source);

        return source;
    }
}

这个小课程的作用是帮助你的控件在你激活其中的控件(即你的ComboBox)时专注于ListBox选择的项目。在ListBox项目中单击鼠标时,它可以正常工作。

现在你所要做的就是将它附加到你的ComboBox上,如下所示:

<DataTemplate x:Key="myDataTemplate">
  <ComboBox
      TitleText="{Binding Title}"
      DescriptionText="{Binding DescriptionText}"
      CotrolHelper:ListBoxHelper.CanFocusParent="true"/>
</DataTemplate>

ControlHelper的位置:

xmlns:ControlHelper="clr-namespace:WhereYouPutYour.ListBoxHelperClass"

最后,要禁用(但我建议设置为Auto)滚动条,您可以使用ListBox中的ScrollViewer附加属性,如下所示:

<ListBox
    x:Name="SettingListBox"
    Template="{StaticResource myDataTemplate}"
    ScrollViewer.VerticalScrollBarVisibility="Disabled" >
    <Item>
        <Setting Title="Foo" Description="Bar">
            <Option>Yes</Option><Option>No</Option>
        </Setting>
    </Item>
</ListBox >

答案 1 :(得分:0)

您可以使用ListBox,只需更改数据的显示方式。例如,此代码默认不具有滚动条。 (我想要滚动条,所以我必须在ScrollViewer中明确地包装整个内容。)

                <ListBox.Template>
                    <ControlTemplate>
                        <StackPanel IsItemsHost="True" >
                        </StackPanel>
                    </ControlTemplate>
                </ListBox.Template>