2016-02-26 43 views
0

我正在將應用程序(從Windows窗體和VB.Net轉換爲WPF)進行更新,以向用戶顯示最近消息的列表。我創建了一個MessageViewModel,一個MessagesListViewModel和兩個自定義用戶控件MessageListUserControlMessageUserControl在ItemsControl中將視圖模型綁定到自定義用戶控件

消息在垂直堆棧面板中使用MessageListUserControl中的ItemsControl列出,並使用MessageuserControl呈現。但是,所有消息都將Message屬性設置爲null,而不是當前消息。

我已經包含在我的代碼下面,如果任何人有關於如何解決綁定的任何想法,我會非常感激,因爲這是我第一次與WPF。

MessageViewModel

using System; 
using System.ComponentModel; 

namespace TestApp 
{ 
    public class MessageViewModel : INotifyPropertyChanged 
    { 
     private string _sender; 

     private string _subject; 

     private string _content; 

     public event PropertyChangedEventHandler PropertyChanged; 

     public string Sender 
     { 
      get { return _sender; } 
      set 
      { 
       _sender = value; 
       NotifyPropertyChanged("Sender"); 
      } 
     } 

     public string Subject 
     { 
      get { return _subject; } 
      set 
      { 
       _subject = value; 
       NotifyPropertyChanged("Subject"); 
      } 
     } 

     public string Content 
     { 
      get { return _content; } 
      set 
      { 
       _content = value.Trim(); 
       NotifyPropertyChanged("Content"); 
      } 
     } 

     private void NotifyPropertyChanged(string property) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(property)); 
      } 
     } 
    } 
} 

MessageListViewModel

using System.Collections.ObjectModel; 

namespace TestApp 
{ 
    public class MessageListViewModel 
    { 
     private readonly ObservableCollection<MessageViewModel> _messages; 

     public ObservableCollection<MessageViewModel> Messages 
     { 
      get { return _messages; } 
     } 

     public MessageListViewModel() 
     { 
      _messages = new ObservableCollection<MessageViewModel>(); 
     } 

     #region Methods 
     public void AddMessage(string sender, string subject, string content) 
     { 

      var vm = new MessageViewModel() 
      { 
       Sender = sender, 
       Subject = subject, 
       Content = content, 
      }; 
      _messages.Insert(0, vm); // Insert it at the top of the list. 
     } 
     #endregion // Methods 
    } 
} 

MessageUserControl

<UserControl x:Class="TestApp.MessageUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:TestApp" 
      mc:Ignorable="d" x:Name="MessageCtrl" Background="White" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <DockPanel> 
     <Border BorderThickness="0,0,0,1" BorderBrush="DarkGray" DockPanel.Dock="Top"> 
      <Grid DockPanel.Dock="Top"> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="60"/> 
        <ColumnDefinition/> 
       </Grid.ColumnDefinitions> 

       <Grid.RowDefinitions> 
        <RowDefinition/> 
        <RowDefinition/> 
       </Grid.RowDefinitions> 

       <TextBlock Name="lblSender" Text="Sender" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="0" FontWeight="Bold" Padding="5"/> 
       <TextBlock Name="txtSender" Text="{Binding Path=Sender, Mode=TwoWay}" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="1" Padding="5"/> 

       <TextBlock Name="lblSubject" Text="Subject" HorizontalAlignment="Left" Grid.Row="1" Grid.Column="0" FontWeight="Bold" Padding="5"/> 
       <TextBlock Name="txtSubject" Text="{Binding Path=Subject, Mode=TwoWay}" HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="1" Padding="5"/> 
      </Grid> 
     </Border> 

     <TextBox BorderThickness="0" Background="Transparent" IsReadOnly="True" Name="txtMessageContent" Text="{Binding Path=Content, Mode=TwoWay}" DockPanel.Dock="Top" Padding="5" VerticalAlignment="Center" HorizontalAlignment="Stretch" TextWrapping="WrapWithOverflow" /> 
    </DockPanel> 
</UserControl> 

MessageListUserControl

<UserControl x:Class="TestApp.MessageListUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:TestApp" 
      mc:Ignorable="d" Background="White" x:Name="MessagesListCtrl" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <DockPanel> 
     <ItemsControl x:Name="MessagesStack" Grid.Column="0" ItemsSource="{Binding Path=Messages}"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <StackPanel Orientation="Vertical"/> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <local:MessageControl Message="{Binding Path=., Mode=TwoWay}" /> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
    </DockPanel> 
</UserControl> 

結果最終看起來像下面,有一個空的主題,發件人和內容:

Empty message details

我也嘗試在中設置DataTemplate中的綁定至{Binding /}如發現here沒有成功,以及設置DataContext={Binding}

當我將用於單個消息顯示的模板XAML直接移動到DataTemplate時,一切正常,但我希望將它分離爲單獨的控件以在其上執行一些額外的邏輯。

+1

UserControls的一般規則:*從不*顯式設置它們的DataContext(就像你在'DataContext =「{Binding Message ...}「'),因爲這會阻止繼承一個DataContext,例如,當你將它放在一個用於ItemControl的ItemTemplate的DataTemplate中時,結果是你的綁定'Message =」{Binding Path =。,Mode = TwoWay} – Clemens

+0

感謝@Clemens現在我已經從'MessageUserControl'中刪除了它,並且使用了WPF Inspector來檢查應用程序,它看起來像'MessageUserControl'的DataContext是null,所以我嘗試設置('DataContext = {Binding}')沒有運氣 - 它仍然是空的! – euantorano

+0

嘗試刪除Content =「{Binding}」!保持其他所有內容不變。還從各個地方刪除Mode = TwoWay,因爲它們根本不需要。 – AnjumSKhan

回答

0

移除

<local:MessageControl Message="{Binding Path=., Mode=TwoWay}" />

不需要它在所有Message財產。

MessageControl中刪除DataContext您已經完成了這項工作。

一切都保持不變,現在它會工作。

DataTemplate將自動獲得它的DataContext作爲MessageViewModel

+0

剛剛嘗試過,但我得到了同樣的結果。 – euantorano

+0

@euantorano請參閱編輯的正確答案。 – AnjumSKhan

相關問題