【问题标题】:How to have a custom display in ListBox with DataTemplate?如何使用 DataTemplate 在 ListBox 中进行自定义显示?
【发布时间】:2019-10-10 21:42:14
【问题描述】:

我需要在 ListBox 中以特定布局显示卡片:

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 中显示的内容:

<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;

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

【问题讨论】:

  • 您必须使用属性,而不是字段。该按钮可以在您的视图模型中将其Command 绑定到ICommand。了解 MVVM。

标签: c# wpf xaml listbox datatemplate


【解决方案1】:

举一个 Sinatr 评论的例子。你应该从 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。一个简单的搜索应该解决如何做到这一点。

以上内容应该足以让您重构代码以使其正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多