【问题标题】:WPF Extended ListBox doesn't find definitionWPF 扩展列表框找不到定义
【发布时间】:2015-08-23 22:21:57
【问题描述】:

已扩展 ListBox 以给我一个水平列表框,即在 XAML 中:

<ListBox x:Class="Renishaw.Inspire.InTheatreCompanion.View.HorizontalListBox"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Style="{x:Null}">

    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel Name="ItemContainer" 
                                    Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>


</ListBox>

在后面的代码中

public partial class HorizontalListBox : ListBox
   {
      public static readonly DependencyProperty IndentItemsProperty = DependencyProperty.Register(
         "IndentItems", typeof(double), typeof(HorizontalListBox), new PropertyMetadata(0.0, new PropertyChangedCallback(OnIndentItemsChanged)));

      public HorizontalListBox()
      {
         InitializeComponent();
      }

      public double IndentItems
      {
         get { return (double)GetValue(IndentItemsProperty); }
         set { SetValue(IndentItemsProperty, value); }
      }

      private static void OnIndentItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
         var horizontalListBox = (HorizontalListBox)d;
         var thickness = new Thickness((double)e.NewValue, 0, 0, 0);
         horizontalListBox.ItemContainer.Margin = thickness;
      }

      public static void SetIndentItems(DependencyObject obj, double thickness)
      {
         obj.SetValue(IndentItemsProperty, thickness);
      }

      public static double GetIndentItems(DependencyObject obj)
      {
         return (double)obj.GetValue(IndentItemsProperty);
      }

   }

假设依赖属性 IndentItems 允许我通过设置用于包含项目的 VirtualizingStackPanel 的边距来将项目缩进设定的数量。但是,尝试构建它会引发一个错误,告诉我“Horizo​​natlListBox 不包含 'ItemContainer' 的定义”,即使它已在 xaml 中指定了该名称。有什么想法我可能会出错吗?

【问题讨论】:

  • @Clemens:在 Horizo​​natlListBox 级别设置边距会产生不同的行为,即,识别列表框而不是列表框中的列表项。这会在滚动时呈现不同的外观。
  • 确实如此!完全错过了那个。如果您将其设置为答案,我会将其标记为正确。 :)

标签: wpf xaml listbox


【解决方案1】:

为此使用转换器怎么样?

<Window x:Class="ListBoxMargins.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ListBoxMargins"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.Resources>
        <local:StackConverter x:Key="StackConverter"/>
    </Grid.Resources>
    <ListBox ItemsSource="{Binding source}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel Name="ItemContainer" 
                                Orientation="Horizontal" 
                                Margin="{Binding RelativeSource={RelativeSource Self}, Path=IsKeyboardFocusWithin, Converter={StaticResource StackConverter}}"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>
</Grid>

public partial class MainWindow : Window
{
    public ObservableCollection<string> source { get; set; }
    public MainWindow()
    {
        InitializeComponent();
        source = new ObservableCollection<string>();
        source.Add("Test element1");
        source.Add("Test element2");
        source.Add("Test element3");
        this.DataContext = this;
    }
}

我没有在这里做所有的检查,但是在我的测试中,面板是缩进的。

public class StackConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool focused = (bool)value;

        if (focused)
        {
            return new Thickness(50);
        }
        else
        {
            return new Thickness(0);
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

【讨论】:

  • 不确定我是否看到使用转换器的好处(那里仍然有硬编码的厚度值)。理想情况下,缩进(厚度)应该是扩展 ListBox 的属性,因此使用依赖属性。
【解决方案2】:

在模板中设置元素的名称不会在声明模板的类中生成成员,即您的 Horizo​​ntalListBox 类中没有 ItemContainer 成员。

除此之外,您的IndentItems 属性似乎是多余的,因为ListBox 已经有一个Padding 属性:

<local:HorizontalListBox Padding="50,0,0,0" .../>

现在可能不再需要派生的 Horizo​​ntalListBox,因为您可以这样写:

<ListBox Padding="50,0,0,0" ...>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
<ListBox/>

【讨论】:

    【解决方案3】:

    您可以比创建新控件更简单地满足您的要求:

    <App.Resources>
        <ItemsPanelTemplate x:Key="HorizontalStackPanelTemplate">
            <VirtualizingStackPanel Orientation="Horizontal" />
        <ItemsPanelTemplate>
    </App.Resources>
    
    <ListBox ItemsSource="{Binding source}" Padding ="50,0,0,0"
             ItemsPanel="{StaticResource HorizontalStackPanelTemplate}" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多