簡體   English   中英

如何添加不同的ListBox項WPF

[英]How to add different ListBox items WPF

我正在實現一個像這個圖像的聊天應用程序: 在此輸入圖像描述

我開始創建一個ListBox並設置一個ListBox.ItemTemplate,但我無法弄清楚我如何控制ListBox添加一個項目的布局作為收到的消息或發送(就像Whatsapp)。

這是我的代碼:

<ListBox Name="ChatListBox" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Background="#00FFFFFF" BorderBrush="{x:Null}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
                            <ListBox.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Background="#00FFFFFF"/>
                                </ItemsPanelTemplate>
                            </ListBox.ItemsPanel>
                            <ListBox.ItemContainerStyle>
                                <Style TargetType="{x:Type ListBoxItem}">
                                    <Setter Property="Focusable" Value="False"/>
                                </Style>
                            </ListBox.ItemContainerStyle>
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <Grid>
                                        <!--If the user sends a msg-->
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="9*"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <Border Grid.Column="0" Margin="0" BorderThickness="1" BorderBrush="#9f9f9f" Background="#c4df9b" CornerRadius="10">
                                            <TextBlock Name="MsgText" Background="#c4df9b" Foreground="Black" TextAlignment="Center" TextWrapping="Wrap" Margin="5" Text="{Binding text}" FontSize="14"/>
                                        </Border>
                                        <Image Grid.Column="1" Source="Images/user.png" Margin="5" Height="{Binding ElementName=MsgText, Path=ActualHeight}"/>
                                        <!--
                                        If the user receives a msg
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="9*"/>
                                        </Grid.ColumnDefinitions>
                                        <Image Grid.Column="0" Source="Images/user.png" Margin="5" Height="{Binding ElementName=MsgText, Path=ActualHeight}"/>
                                        <Border Grid.Column="1" Margin="0" BorderThickness="1" BorderBrush="#9f9f9f" Background="#c4df9b" CornerRadius="10">
                                            <TextBlock Name="MsgText" Background="#c4df9b" Foreground="Black" TextAlignment="Center" TextWrapping="Wrap" Margin="5" Text="{Binding text}" FontSize="14"/>
                                        </Border>-->
                                    </Grid>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>

這是我的c#代碼:

List<ChatItem> chatItem = new List<ChatItem>();
chatItem.Add(new ChatItem() { text = "Hello...", isFromUser = false });
        chatItem.Add(new ChatItem() { text = "hi!", isFromUser = true });
        chatItem.Add(new ChatItem() { text = "this is a test, this is a test, this is a test, this is a test, this is a test, this is a test, this is a test, this is a test, this is a test, this is a test", isFromUser = false });
        ChatListBox.ItemsSource = chatItem;

這就是ListBox的處理方式:

在此輸入圖像描述

有沒有辦法在帶有WPF的ListBox中添加IF語句? 或者我如何控制要添加的ListBox.ItemTemplate。

如果您的消息屬於同一類,則可以使用itemsTemplateSelector,如http://codingbandit.com/blog/?p=8

如果有不同的類,你應該使用datatemplate數據類型屬性,如在條件列表itemtemplate或datatemplate在WPF中

也許這會給你一個想法

XAML

<Window x:Class="Q1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Q1"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <DataTemplate x:Key="intDataTemplate">
        <TextBox Text="{Binding Path=.}" Width="80"/>
    </DataTemplate>
    <DataTemplate x:Key="stringDataTemplate">
        <TextBlock Text="{Binding Path=.}"/>
    </DataTemplate>
    <local:MyDataTemplateSelector IntDataTemplate="{StaticResource intDataTemplate}"
                                  StringDataTemplate="{StaticResource stringDataTemplate}"
                                  x:Key="myDataTemplateSelector"/>
</Window.Resources>
<Grid>
    <ListBox x:Name="myListBox" ItemsSource="{Binding}"
             ItemTemplateSelector="{StaticResource myDataTemplateSelector}">

    </ListBox>
</Grid>

代碼隱藏

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Q1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            List<System.Object> myList = new List<object>();
            myList.Add(1);
            myList.Add("Alpha");
            myList.Add(2);
            myList.Add("Beta");
            myList.Add(3);
            myList.Add("Gamma");
            myListBox.DataContext = myList;
        }
    }

}

DataTemplateSelector

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Q1
{
    public class MyDataTemplateSelector : System.Windows.Controls.DataTemplateSelector
    {
        public System.Windows.DataTemplate IntDataTemplate { get; set; }
        public System.Windows.DataTemplate StringDataTemplate { get; set; }
        public MyDataTemplateSelector()
        {
            IntDataTemplate = new System.Windows.DataTemplate();
            StringDataTemplate = new System.Windows.DataTemplate();
        }
        public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
        {
            if (item is Int32)
            {
                return IntDataTemplate;
            }
            else
            {
                return StringDataTemplate;
            }
        }
    }
}

另一種選擇是簡單地使用數據觸發器:

<DataTemplate x:Key="ToTemplate">
    ... etc ...
</DataTemplate>

<DataTemplate x:Key="FromTemplate">
    ... etc ...
</DataTemplate>

<Style TargetType="ListBoxItem">
    <Style.Triggers>
        <DataTrigger Binding="{Binding isFromUser}" Value="false">
            <Setter Property="Template" Value="{StaticResource ToTemplate}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding isFromUser}" Value="true">
            <Setter Property="Template" Value="{StaticResource FromTemplate}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

您可以使用DataTemplateSelector根據您的數據選擇模板,這是一個示例。

對於此示例,我將使用消息,客戶端消息和服務器消息:

public abstract class Message
{
    public string Content { get; set; }

    public override string ToString()
    {
        return Content;
    }
}

public class ServerMessage : Message
{

}

public class ClientMessage : Message
{

}

通過這種方式,我可以檢查對象的類型並應用某些模板。

讓我們定義我們的模板和選擇器:

XAML:

    <DataTemplate x:Key="clientTemplate" >
        <TextBlock Text="{Binding Content}"
                   Foreground="Red"/>
    </DataTemplate>

    <DataTemplate x:Key="serverClient">
        <TextBlock Text="{Binding Content}"
                   Foreground="Green"/>
    </DataTemplate>

    <local:MessageTemplateSelector x:Key="messageSelector" 
                                   ServerTemplate="{StaticResource serverClient}"
                                   ClientTemplate="{StaticResource clientTemplate}"/>

DataTemplateSelector

public class MessageTemplateSelector : DataTemplateSelector
{
    public DataTemplate ClientTemplate { get; set; }

    public DataTemplate ServerTemplate { get; set; }

    public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
    {
        if (item.GetType() == typeof(ClientMessage))
            return ClientTemplate;

        return ServerTemplate;
    }
}

首先,正如您所看到的,我在Selector上創建了兩個DataTemplate屬性,我通過XAML設置它,這樣做很容易檢索DataTemplate,最后我只是比較參數接收的項目,即綁定對象(消息),並檢查其類型並返回模板。

就是這樣,它就像預期的那樣工作。

在此輸入圖像描述

更新:假設您希望模板根據其類型進行項目,就像我的示例一樣,您可以在不使用TemplateSelector的情況下使用相同的內容,您可以定義模板的DataType:

<Window.Resources>
    <DataTemplate DataType="{x:Type local:ClientMessage}">
        <TextBlock Text="{Binding Content}"
                   Foreground="Red"/>
    </DataTemplate>

    <DataTemplate DataType="{x:Type  local:ServerMessage}">
        <TextBlock Text="{Binding Content}"
                   Foreground="Green"/>
    </DataTemplate>
</Window.Resources>

這樣,將根據對象的類型自動選擇模板。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM