【问题标题】:Binding to the selected item in an ItemsControl绑定到 ItemsControl 中的选定项
【发布时间】:2011-01-09 15:55:42
【问题描述】:

我创建了一个自定义ComboBox,如下所示:(注意,代码不正确,但您应该了解一般概念。)ComboBox 包含两个重要的依赖属性:TitleTextDescriptionText

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

我想用这个ComboBox 来显示范围广泛的选项。我创建了一个名为 Setting 的类,它继承自 DependencyObject 以创建可用项目,我创建了一个 DataTemplate 以将此 Settings 对象的内容绑定到我的 ComboBox 并创建了一个 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>

我希望将所选ComboBoxDescriptionText(由ComboBox 控件的IsFocus 或弹​​出窗口的IsOpen 属性选择)放置在Description TextBlock 在我的UserControl 中。

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

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

最后的目标是遍历所有项目(也许将它们放入ObservableCollection 或某种形式,然后将它们保存到我的设置文件中。

【问题讨论】:

  • 我不完全清楚你在这里尝试什么。您是否有代码隐藏,或者您只是使用绑定?
  • 我有一个代码隐藏文件,但目前它并没有真正使用。每个 ComboBox 都包含一个关于它改变的选项的小描述,当您选择 ComboBox 项目(获得焦点或弹出窗口打开)时,想法是使用正确的描述更新右侧的 Description TextBlock。

标签: wpf xaml data-binding binding itemscontrol


【解决方案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"

最后,要禁用(但我建议设置为自动)滚动条,您可以像这样在 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 >

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-12
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 2011-12-04
      • 1970-01-01
      • 2011-11-30
      相关资源
      最近更新 更多