简体   繁体   English

使用Canvas作为ItemsPanelTemplate选择绑定的ListBox项目

[英]Selecting bound ListBox items with Canvas as ItemsPanelTemplate

I'm writing a scheduling tool and I want to have a view similar to "Day", which is available in many calendar apps. 我正在编写一个计划工具,希望有一个类似于“日”的视图,该视图可在许多日历应用程序中使用。

It's done as a ListBox so the user could select some event. 它作为一个ListBox完成,因此用户可以选择一些事件。 The problem occurs when I'm trying to bind the events - selection doesn't work as expected. 当我尝试绑定事件时会发生问题-选择无法按预期进行。 By this I mean that it looks like stretched to the very top of the container, plus the click event doesn't get handled on the element but on the space between the element and the top edge of the container. 我的意思是,它看起来像一直延伸到容器的顶部,而且click事件不会在元素上处理,而是在元素和容器顶部边缘之间的空间上得到处理。

Here's an example: on the left side - how it should work and look, this is done by manually placing two ListBoxItems. 这是一个示例:在左侧-它的工作方式和外观,这是通过手动放置两个ListBoxItems来完成的。 On the right side, using binding. 在右侧,使用绑定。

在此处输入图片说明在此处输入图片说明

I compared visual trees of both cases with a WPF debug tool and there's small difference in eg ContentPresenter stuff, but I don't understand exactly what happens there, why the difference occurs and how I can remove it. 我将两种情况的可视化树与WPF调试工具进行了比较,例如ContentPresenter的内容差异很小,但是我不确切了解那里发生了什么,为什么会发生差异以及如何删除差异。

Here is my XAML: 这是我的XAML:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="PLA1.MainWindow"
    x:Name="Window"
    xmlns:local="clr-namespace:PLA1"
    Title="MainWindow"
    Width="640" Height="480">

    <Window.Resources>
        <local:MarginConverter x:Key="marginConverter"/>
    </Window.Resources>

    <Grid x:Name="LayoutRoot">
        <ListBox Margin="8,8,0,8" Background="#C9BBC0FF" HorizontalAlignment="Left" Width="160">
           <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <ListBoxItem Margin="{Binding Path=StartMinutes, Converter={StaticResource marginConverter}}" Height="{Binding Path=Duration}" Width="150" Background="#8000FF00" Foreground="White" BorderThickness="2" BorderBrush="#80000000">
                        <StackPanel>
                            <TextBlock Text="{Binding Path=Name}" Margin="5,0,0,0" Width="130" TextWrapping="Wrap" FontWeight="Bold" FontSize="18" />
                            <TextBlock Text="{Binding Path=Place}"  Margin="8,0,0,0" FontSize="14"/>
                        </StackPanel>
                    </ListBoxItem>
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.Effect>
                <DropShadowEffect Opacity="0.625"/>
            </ListBox.Effect>

            <!-- uncomment these two lines to test binding -->
            <!--local:Event Duration="200" StartMinutes="60" Name="Sprawdzian" Place="EA32" />
            <local:Event Duration="120" StartMinutes="300" Name="Oddanie projektu" Place="308" /-->

            <ListBoxItem Margin="0,60,0,0" Height="200" Width="150" Background="#8000FF00" Foreground="White" BorderThickness="2" BorderBrush="#80000000">
                <StackPanel>
                    <TextBlock Text="Sprawdzian" Margin="5,0,0,0" Width="130" TextWrapping="Wrap" FontWeight="Bold" FontSize="18" />
                    <TextBlock Text="EA32"  Margin="8,0,0,0" FontSize="14"/>
                </StackPanel>
            </ListBoxItem>      

            <ListBoxItem Margin="0,300,0,0" Height="120" Width="150" Background="#8000FF00" Foreground="White" BorderThickness="2" BorderBrush="#80000000">
                <StackPanel>
                    <TextBlock Text="Oddanie projektu" Margin="5,0,0,0" Width="130" TextWrapping="Wrap" FontWeight="Bold" FontSize="18" />
                    <TextBlock Text="308"  Margin="8,0,0,0" FontSize="14"/>
                </StackPanel>
            </ListBoxItem>  
        </ListBox>
    </Grid>
</Window>

Event class: 活动类别:

public class Event
{
    public int StartMinutes { get;set; }
    public int Duration { get; set; }
    public string Name { get; set; }
    public string Place { get; set; }

    public Event() { }
}

MarginConverter class: MarginConverter类:

public class MarginConverter : IValueConverter
{
    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return new Thickness(0, (int)(value), 0, 0);
    }

    public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

You should add style to ListBoxItem in ListBox resources where you set appropriate properties and change ItemTemplate : 您应该在设置适当属性并更改ItemTemplate ListBox资源中向ListBoxItem添加样式:

<ListBox Margin="8,8,0,8" Background="#C9BBC0FF" HorizontalAlignment="Left" Width="160">
    <ListBox.Resources>                   
        <Style TargetType="ListBoxItem">
            <Setter Property="Margin" Value="{Binding Path=StartMinutes, Converter={StaticResource marginConverter}}" />
            <Setter Property="Height" Value="{Binding Path=Duration}" />
            <Setter Property="Foreground" Value="White" />
            <Setter Property="BorderThickness" Value="2" />
            <Setter Property="BorderBrush" Value="#80000000" />
            <Setter Property="Width" Value="150" />
            <Setter Property="Background" Value="#8000FF00" />
        </Style>
    </ListBox.Resources>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ListBox.ItemTemplate>
        <DataTemplate>                    
                <StackPanel>
                    <TextBlock Text="{Binding Path=Name}" Margin="5,0,0,0" Width="130" TextWrapping="Wrap" FontWeight="Bold" FontSize="18" />
                    <TextBlock Text="{Binding Path=Place}"  Margin="8,0,0,0" FontSize="14"/>
                </StackPanel>                        
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.Effect>
        <DropShadowEffect Opacity="0.625"/>
    </ListBox.Effect>

    <!-- uncomment these two lines to test binding -->
    <local:Event Duration="200" StartMinutes="60" Name="Sprawdzian" Place="EA32" />
    <local:Event Duration="120" StartMinutes="300" Name="Oddanie projektu" Place="308" />

    <!--<ListBoxItem Margin="0,60,0,0" Height="200" Width="150" Background="#8000FF00" Foreground="White" BorderThickness="2" BorderBrush="#80000000">
        <StackPanel>
            <TextBlock Text="Sprawdzian" Margin="5,0,0,0" Width="130" TextWrapping="Wrap" FontWeight="Bold" FontSize="18" />
            <TextBlock Text="EA32"  Margin="8,0,0,0" FontSize="14"/>
        </StackPanel>
    </ListBoxItem>

    <ListBoxItem Margin="0,300,0,0" Height="120" Width="150" Background="#8000FF00" Foreground="White" BorderThickness="2" BorderBrush="#80000000">
        <StackPanel>
            <TextBlock Text="Oddanie projektu" Margin="5,0,0,0" Width="130" TextWrapping="Wrap" FontWeight="Bold" FontSize="18" />
            <TextBlock Text="308"  Margin="8,0,0,0" FontSize="14"/>
        </StackPanel>
    </ListBoxItem>-->
</ListBox>

Visual tree with two ListBoxItem items: 带有两个ListBoxItem项的可视树:

在此处输入图片说明

In this example everything is ok, Height and Margin properties are setting in code. 在此示例中,一切正常,在代码中设置了HeightMargin属性。

Visual tree with two Event items: 具有两个Event项的可视树:

在此处输入图片说明

In this example you defined ItemTemplate as ListBoxItem but by default ListBox also will add container ListBoxItem so you have two ListBoxItem 's and here is problem because you set height and margin only for the inner ListBoxItem . 在此示例中,您将ItemTemplate定义为ListBoxItem但默认情况下, ListBox还将添加容器ListBoxItem因此您有两个ListBoxItem ,这是问题所在,因为您仅为内部ListBoxItem设置了高度和边距。 Outer ListBoxItem has the default properties. 外部ListBoxItem具有默认属性。

If you want to check this by yourself you can use to do this snoop ( http://snoopwpf.codeplex.com/ ). 如果要自己检查,可以使用此监听( http://snoopwpf.codeplex.com/ )。

Try updating your ListBox as below: 尝试如下更新您的ListBox:

  <ListBox Margin="8,8,0,8" Background="#C9BBC0FF" HorizontalAlignment="Left" Width="160">
       <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemContainerStyle>
           <Style TargetType="ListBoxItem">
                    <Setter Property="Height" Value="{Binding Duration}"/>
                     <Setter Property="Margin" Value="{Binding Path=StartMinutes, Converter={StaticResource marginConverter}}" />
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                    <StackPanel Background="#8000FF00" BorderThickness="2" BorderBrush="#80000000">
                        <TextBlock Text="{Binding Path=Name}" Margin="5,0,0,0" Width="130" TextWrapping="Wrap" FontWeight="Bold" FontSize="18" />
                        <TextBlock Text="{Binding Path=Place}"  Margin="8,0,0,0" FontSize="14"/>
                    </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM