2016-09-04 17 views
0

このフォーラムで検索しましたが、特定のシナリオでは解決策が見つかりませんでした。WPF ListBoxが更新されていません

私はWPFとMVVMを理解しようとしており、私はこれに対して単純なWPFを構築しています。

私のデータモデルは、(私はここにINotifyPropertyChangedの実装およびコンストラクタはすべてのプロパティを初期化します)です。(後ろにWPFコードによって使用される)

namespace MyApp.ui.Models 
{ 
    public class Server : INotifyPropertyChanged 
    { 
     private int id; 
     public int ID 
     { 
      get { return id; } 
      set { id = value; } 
     } 

     private string name; 
     public string Name 
     { 
      get { return name; } 
      set { name = value; OnPropertyChanged(Name); } 
     } 

     private string ipAddress; 
     public string IPAddress 
     { 
      get { return ipAddress; } 
      set { ipAddress = value; OnPropertyChanged(IPAddress); } 
     } 

     public Server(int ServerID, string ServerName, string ServerIpAddress) 
     { 
      ID = ServerID; 
      Name = ServerName; 
      IPAddress = ServerIpAddress; 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     private void OnPropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if(handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
} 

私のViewModel:

namespace MyApp.ui.ViewModels 
{ 
    public class ServersViewModel 
    { 
     private ObservableCollection<Server> server; 
     public ObservableCollection<Server> Servers 
     { 
      get { return server; } 
      set { server = value; } 
     } 

     public ServersViewModel() 
     { 
      Servers = new ObservableCollection<Server> 
      { 
       new Server(001, "Server001", @"192.168.254.3"), 
       new Server(002, "Server002", @"100.92.0.200"), 
       new Server(003, "Server003", @"64.32.0.3"), 
       new Server(004, "Server004", @"172.10.0.4"), 
       new Server(005, "Server005", @"165.23.0.233"), 
       new Server(006, "Server006", @"81.22.22.6"), 
       new Server(007, "Server007", @"10.10.0.7") 
      }; 
     } 

     public void ChangeServerNames() 
     { 
      //Before Change 
      foreach (var item in Servers) 
      { 
       MessageBox.Show(item.Name); 
      } 

      int count = 1000; 

      foreach (var item in Servers) 
      { 
       item.Name = "Server" + count.ToString(); 
       count += 1000; 
      } 

      //After Change 
      foreach (var item in Servers) 
      { 
       MessageBox.Show(item.Name); 
      } 
     } 
    } 
} 

私のWPFメインビュー(メインメニュー)は、次のXAMLコード(リストボックスを含み、各リストボックスアイテムに1つのチェックボックス+画像+テキストブロックを含む)を持つカスタムユーザーコントロール(ExplorerView)を読み込みます。

<UserControl x:Class="MyApp.ui.Views.ExplorerView" 
      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:MyApp.ui.Views" 
      mc:Ignorable="d" 
      d:DesignHeight="400" d:DesignWidth="200"> 
    <Grid> 
     <ListBox ItemsSource="{Binding Servers}" Margin="2"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <CheckBox VerticalContentAlignment="Center" Margin="4"> 
         <StackPanel Orientation="Horizontal"> 
          <Image Source="/resources/server64.png" Height="30" Margin="4"></Image> 
          <TextBlock Text="{Binding Name}" 
            VerticalAlignment="Center" Margin="4"></TextBlock> 
         </StackPanel> 
        </CheckBox> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </Grid> 
</UserControl> 

最後に、MainViewコードの後ろにServersViewModelがロードされ、ExplorerViewコントロールがデータをバインドできるようにします。

私は2つの質問持っている、と述べた
namespace MyApp.ui 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public ServersViewModel context { get; set; } 

     public MainWindow() 
     { 
      InitializeComponent(); 

      context = new ServersViewModel(); 
      DataContext = context; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      context.ChangeServerNames(); 
     } 
    } 
} 

:あなたは私がServersViewModel.ChangeServerNames()メソッドを呼び出しボタンのクリックイベントを実装MAINVIEWで、見ることができるように

1)。問題は、ExplorerView ControlのTextBlockに更新されたデータが表示されないことです。

I ChangeServerNames()また、変更前と変更後の値を表示するためにMessageBoxを使用していますが、値が変更されていることがわかります。なぜListBox/TextBlockが更新されていないのかわかりません。 (私はすでに他の多くの解決策を試しましたが、それを動かすことはできません...)

2)私は、MainViewのCodeBehindと他のすべてのビューにInitializeComponent()が含まれている必要があります。と "DataContext = context;"最大で... これが当てはまる場合、ボタンクリックのイベントとその他のイベントはどこに配置する必要がありますか?最後に

メインウィンドウXAMLのコード:

<Window 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:MyApp.ui" 
     xmlns:Views="clr-namespace:MyApp.ui.Views" 
     x:Class="MyApp.ui.MainWindow" 
     mc:Ignorable="d" 
     Title="Server" MinHeight="720" MinWidth="1024" 
     Height ="720" Width="1024"> 
    <Grid Margin="2"> 

     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="200" /> 
      <ColumnDefinition Width="Auto"/> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 

     <Grid.RowDefinitions> 
      <RowDefinition Height="41*"/> 
      <RowDefinition Height="608*"/> 
      <RowDefinition Height="30"/> 
     </Grid.RowDefinitions> 

     <GridSplitter Grid.Column="1" Grid.Row="1" 
       HorizontalAlignment="Center" 
       VerticalAlignment="Stretch" 
       Background="Gray" 
       ShowsPreview="True" 
       Width="4" Margin="0,2,0,4" 
       /> 

     <Views:MenuView Grid.ColumnSpan="3"/> 
     <Views:FooterView Grid.Row="2" Grid.ColumnSpan="3" /> 
     <Views:ExplorerView Grid.Column="0" Grid.Row="1" /> 

     <!--Temp Tests--> 
     <StackPanel Margin="12" Grid.Column="3" Grid.Row="1" Width="Auto" Height="Auto" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left"> 
      <Button Margin="4" Width="120" Height="30" Content="Change Data Test..." Click="Button_Click" /> 
     </StackPanel> 

    </Grid> 
</Window> 

はお時間をいただき、ありがとうございます...

答えて

2

[OK]を、私が見つけた問題...

代わりの

set { name = value; OnPropertyChanged(Name); } 
set { ipAddress = value; OnPropertyChanged(IPAddress); } 

メソッドコールで文字列引数のQuotesが見つかりません 正しいf ORMは、コンパイラがエラー....方法 ます。private voidはOnPropertyChangedを(文字列propertyNameの) は、入力引数として文字列のために「頼む」です投げるdidn`tのこと

set { name = value; OnPropertyChanged("Name"); } 
set { ipAddress = value; OnPropertyChanged("IPAddress"); } 

奇妙です。これらのエラーを(私が見つけたことを)避けるために

とにかく最高のは、このようなイベント(発信者用品それ `s自身のパブリック名)を記述することです:

今 ​​

私にできること

set { name = value; OnPropertyChanged(); } 
set { ipAddress = value; OnPropertyChanged(); } 

ありがとうございます。

+0

'IPAddress'は文字列です。コンパイラがあなたのために何もできないことは、悲しいことです。あなたはCallerMemberNameが正解であることは間違いありません。それは型付きのviewmodelプロパティを作成するためのVSスニペットです。 –

+0

良い点、ありがとうございます。 –

関連する問題