2015-11-07 65 views
2

我採取這樣的形象聊天應用: enter image description here如何添加不同的ListBox中的項目WPF

我開始通過創建一個列表框和設置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; 

這是列表框是如何redered:

enter image description here

有什麼辦法在WPF中添加一個IF語句的列表框?或者我如何控制添加哪個ListBox.ItemTemplate。

+2

爲什麼不使用數據模板選擇器並根據消息屬性選擇正確的電話模板? –

+0

@BenjaminBaumann你能給我一個dataTemplate選擇器的例子嗎? –

回答

1

你可以使用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,最後我只比較由綁定對象(Message)參數接收的項目,並檢查它的鍵入並返回模板。

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

enter image description here

UPDATE:讓我們假設你想模板您的項目根據其類型,就像我的例子,可以將這個上面沒有使用TemplateSelector同樣的事情,你可以定義模板的數據類型:

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

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

2

也許這會給你一個想法

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

} 

DataTempla teSelector

​​3210
+0

@Vivex Saurav「l」代表什麼?

+0

這是一個命名空間xmlns:l =「clr-namespace:DataTemplates」你定義檢查更新後的答案 –

+0

@Vivex Saurav DependencyPropertyInfo無法找到 –

1

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

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