如何使用DataTemplate在ListBox中显示自定义显示?

时间:2019-05-24 09:48:21

标签: c# wpf xaml listbox datatemplate

我需要以特定布局在列表框中显示卡片:

https://imgur.com/a/0U8eqTc

我试图找到一种使用2种类型的DataTemplate的方法,但是我不知道该怎么做。我决定制作一个包含6张卡片模板的模板(像这样):

https://imgur.com/VrOlYcR

这是我当前的模板的样子:

<ControlTemplate x:Key = "CardTemplate" TargetType = "Button">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="4*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Image Grid.Row="0" Source="{Binding Path=Image}"/>
        <TextBlock Grid.Row="1" Text="{Binding Path=Titre}"/>
    </Grid>
</ControlTemplate>

<DataTemplate x:Key="DataTemplate">
    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>

        <Button Grid.Column="0" Grid.Row="0" Template="{StaticResource CardTemplate}"/>

        <Grid Grid.Column="1" Grid.Row="0">
            <Grid.RowDefinitions>
                <RowDefinition Height="1*"/>
                <RowDefinition Height="1*"/>
            </Grid.RowDefinitions>
            <Button Grid.Row="0" Template="{StaticResource CardTemplate}"/>
            <Button Grid.Row="1" Template="{StaticResource CardTemplate}"/>
        </Grid>

        <Grid Grid.Column="0" Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="1*"/>
                <RowDefinition Height="1*"/>
            </Grid.RowDefinitions>
            <Button Grid.Row="0" Template="{StaticResource CardTemplate}"/>
            <Button Grid.Row="1" Template="{StaticResource CardTemplate}"/>
        </Grid>

        <Button Grid.Column="1" Grid.Row="1" Template="{StaticResource CardTemplate}"/>

    </Grid>
</DataTemplate>

我打算显示在列表框中:

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
         Name="ListBox" ItemTemplate="{DynamicResource DataTemplate}" 
         ScrollBar.Scroll="ScrollOnBottom">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

这是我背后的鳕鱼的基本工作原理:

class Cards
{
    public List<Card> cards; // list of 6 Card objects
}

class Card
{
    string title;
    BitmapImage image;

    public string Title { get => title; set => title = value; }
    public BitmapImage Image { get => image; set => image = value; }
}

ObservableCollection<Cards> cc = new ObservableCollection<Cards>();
/*

Cards are already filled with 6 Card
cc filled with Cards

*/
formationListBox.ItemsSource = cc;

这是问题所在,它显示正确数量的Cards,但是按钮为空。我不知道如何将特定对象绑定到每个按钮。

1 个答案:

答案 0 :(得分:1)

举一个辛纳特评论的例子。您应该从Mvvm的角度来解决这个问题。首先,您应该为此窗口所在的视图添加一个视图模型。它将包含一个对象列表,DisplayCards每个对象将存储字符串和图像。

public class DisplayCard : INotifyPropertyChanged
{
    private string _title;
    public string Title
    {
        get { return _title; }
        set
        {
            if (value != _title) { _title = value; RaisePropertyChanged(); }
        }
    }
    private string _cardImage;
    public string CardImage
    {
        get { return _cardImage; }
        set
        {
            if (value != _cardImage) { _cardImage = value; RaisePropertyChanged(); }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
public class YourViewVM : INotifyPropertyChanged
{
    private ObservableCollection<DisplayCard> _cardCollection;
    public ObservableCollection<DisplayCard> CardCollection
    {
        get { return _cardCollection; }
        set
        {
            if (value != _cardCollection) { _cardCollection = value; RaisePropertyChanged(); }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

然后,您需要将列表CardCollection设置为ListBox的ItemSource。然后使用数据模板将DisplayCards属性绑定到包含的对象。

<ListBox Name="lbTodoList" HorizontalContentAlignment="Stretch" ItemSource="{Binding CardCollection}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="4*"/>
          <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Image Grid.Row="0" Source="{Binding Image}"/>
        <TextBlock Grid.Row="1" Text="{Binding Title}"/>
      </Grid>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

您需要确保将YourViewVM设置为视图的DataContext。一个简单的搜索应该可以解决该问题。

以上内容足以使您重构代码,使其可以正常工作。