如何将不同的Horizo​​ntalAlignment设置为ListBoxItems

我昨天发了一个问题,但我想我没能正确解释。

让我再尝试一次。

所以这是我的目标:

在此处输入图像描述

红色气泡表示传入消息,蓝色气泡表示传出消息。 我可以使用以下xaml代码更精确地描述它。 请注意,以下代码仅解释了当我的实际xaml代码(带有一些DataTemplates)编译时我希望得到的内容(WPF将使用DataTemplates为我自动填充数据)。 :

                           

为了实现这个目标,我写道:

            

请注意,上面的代码中没有指定对齐,因为我真的不知道如何使用模板分别为ListBoxItem设置不同的对齐方式。 因此,这将导致默认情况下所有蓝色和红色网格都向左对齐的情况。

我的第一种方法包括一个数据模板选择器(省略了传入消息的模板):

                 

但这没效果。 因为包装语音气泡的Grid不会自动扩展,所以GridGrid的对齐无关紧要(紧密配合)。

然后我去寻找如何在StackPanel扩展Grid ,并且没有运气。

经过数小时的谷歌搜索,试验和错误,我决定自己定义ItemsPanelTemplate的模板。 我的Message对象中有一个属性可以帮助我告诉来自传出消息的传入消息。 但我不知道如何创建ItemsPanelTemplate选择器(为了记录,Google告诉我Windows Phone 8不支持Style.Trigger )。

所以我的问题是: 如何为 ListBoxItems 设置不同的Horizo​​ntalAlignment

BTW, ItemsPabelTemplate看起来像这样:

      

非常感谢你的耐心等待。 我已经在这里疯狂地绝望……这么浪费了很多时间……

注意:我没有Phone SDK,所以不得不使用普通的WPF应用程序。 我没有使用触发器,因为你提到它们不起作用。

所以我敲了一个看起来像这样的简单应用程序

在此处输入图像描述

这是代码:

App.xaml.cs

 public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); var mainvm = new MainWindowViewModel(); var window = new MainWindow { DataContext = mainvm }; window.Show(); mainvm.Messages.Add(new OutgoingMessage{ MessageContent = "Help me please!"}); mainvm.Messages.Add(new IncomingMessage { MessageContent = "What do you want" }); mainvm.Messages.Add(new OutgoingMessage { MessageContent = "I want a ListBox" }); mainvm.Messages.Add(new IncomingMessage { MessageContent = "Then?" }); mainvm.Messages.Add(new OutgoingMessage { MessageContent = "But the Grid won't fill" }); } } 

MainWindow.xaml

                   

ViewModelBase.cs

 public class ViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); } protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { var handler = this.PropertyChanged; if (handler != null) { handler(this, e); } } } 

MainWindowViewModel:

 public class MainWindowViewModel : ViewModelBase { public MainWindowViewModel() { Messages = new ObservableCollection(); } public ObservableCollection Messages { get; protected set; } } 

Message.cs:

 public abstract class Message : ViewModelBase { private string _messageContent; public string MessageContent { get { return this._messageContent; } set { this._messageContent = value; this.OnPropertyChanged("MessageContent"); } } } 

OutgoingMessage.cs

 public class OutgoingMessage : Message { } 

IncomingMessage.cs

 public class IncomingMessage : Message { } 

如何工作我覆盖应用程序启动,以便我可以创建视图模型来填充我的UI。 您可以在App.xaml.cs代码中看到我创建Window并显示它,然后添加消息。 我打算使用计时器但是很懒。

如果您查看MainWindow.xaml,您会注意到我定义了2个DataTemplates。 其中一个目标是我的IncomingMessageViewModel,另一个目标是OutogingMessageViewModel。 本地前缀是我的应用程序命名空间的别名。 我有一个ItemsControl,可以包含基类型Message类,这样我就可以在同一个集合中同时拥有Incoming和Outgoing消息。 这绑定到MainWindowViewModel类的Messages属性。 将传入和传出消息作为两个单独的类很重要,因为这是使这项工作成为可能的魔力。

另一种技术是使用带有样式选择器绑定到属性的属性作为其他答案建议之一,但这意味着我必须处理我的ViewModel中的UI特定逻辑(我不喜欢做)。

要更改任一Message类型的外观,只需更改相应DataTemplate中的xaml代码即可。

希望这可以帮助。

在WPF中,您需要添加

     

到你的ListBox并将“WHATEVER”设置为具有指定对齐的项目的属性…我不知道这是否适用于Windows Phone,但它似乎值得一试,因为你没有提到ItemContainerStyle .. 。

而不是使用Grid,而是使用DockPanel和Horizo​​ntalAlignment =“Stretch”。

至于数据对齐,假设您正在使用ItemsSource,那么有一些解决方法。

首先,最简单的方法是将Horizo​​ntalAlignment WPF属性添加到消息类中。 消息类将确定Horizo​​ntalAlignment是左还是右。 但是,这将使UI的依赖性更高。

代码将是这样的:

  

其次,更好(或干净)的方法是使用转换器(IValueConverter)进行Horizo​​ntalAlignment绑定。 它更难,你必须定义自己的转换器,但你的代码将更整洁。 然后您的消息有一个收入或结果消息的枚举,名为MessageType。 然后在您的转换器中定义它:

 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if(parameter is MessageType){ if(((MessageType)parameter) == MessageType.Income){ return HorizontalAlignment.Left; } else{ return HorizontalAlignment.Right; } } } 

上面的代码未经过测试,因此请考虑错误。 有关Converter的实现,请在某些地方搜索。 没有帮助源我仍然无法生成Converter绑定:)

尝试这个并根据传入设置属性为Left和Outgoing为Right

          

那将是我肮脏的工作榜样

代码隐藏

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var l = new List(); for(int i=0;i<5;i++) { l.Add(new lItem(true,"aaa"+i)); l.Add(new lItem(false,"bbb"+i)); } sads.ItemsSource = l; } } public class lItem { public string Text { get; set; } public Brush Color { get; set; } public HorizontalAlignment alig { get; set; } public lItem(bool ss, string str) { Text = str; Color = Brushes.Blue; alig = HorizontalAlignment.Right; if (ss) { Color = Brushes.Red; alig = HorizontalAlignment.Left; } } } 

XAML

            

我建议使用触发器而不是在ViewModel中定义可视部件