私はまだ WPF にかなり慣れていないので、開発中のアプリケーションを変更して、できる限り MVVM パターンに従い始めることにしました。リスト ボックスでコンテンツ コントロールのビュー モデルを指定しようとすると、問題が発生します。私はしばらくこれに固執しており、インターネットを検索しても答えが得られません。
何らかの理由で、リスト ボックスに含まれるビュー モデルの新しいインスタンスが、コンテンツ コントロールのデータ コンテキストとして生成されています。デバッグ中に、リスト ボックスに必要なビュー モデルが含まれていること、およびリスト ボックスで選択した項目が実際にリスト ボックスが選択している項目であることを確認しましたが、コンテンツ コントロールは選択内容に基づいて変化します。コンテンツ コントロールを設定するビュー モデルはありますが、リスト ボックスの設定元のコレクションにはありません。そして、削除ボタンを使用して、コンテンツ コントロールのビュー モデルを何らかの方法で削除できます。しかし、リスト ボックスで選択を変更したり、コレクションに新しい項目を追加したりすると、コンテンツ コントロールに新しいビュー モデルが入力されますが、これは再びコレクションにはありません。なぜこれを行っているのか、コードの何がこの動作を示唆しているのか、私にはわかりません。
私は自分が間違っていることを理解しようとする簡単なアプリケーションを作成しました。それは私の問題を完全に再現します。ボタンがMVVVMに準拠していないと確信しています(ビューモデルに含まれるコマンドを実行して、これまで読んできたものからMVVMに準拠する必要があります)が、問題がなくても存在するため、今のところそれは私の主な関心事ではありませんボタン。
MainWindow.xml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="440" Width="436">
<Window.DataContext>
<local:mwvm/>
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type local:ucvm}">
<local:uc/>
</DataTemplate>
</Window.Resources>
<Grid>
<Button Content="a" HorizontalAlignment="Left" Margin="323,351,0,0" VerticalAlignment="Top" Width="95" Click="Button_Click"/>
<Button Content="r" HorizontalAlignment="Left" Margin="323,378,0,0" VerticalAlignment="Top" Width="95" Click="Button_Click_1"/>
<ContentControl Margin="10,10,110,10" Content="{Binding SelectedItem, ElementName=lb_UCs}"/>
<ListBox x:Name="lb_UCs" HorizontalAlignment="Left" Height="336" Margin="323,10,0,0" VerticalAlignment="Top" Width="95" ItemsSource="{Binding UCs}" DisplayMemberPath="CoolText"/>
</Grid>
</Window>
MainWindow.xaml.cs
public partial class PanelPartsView : UserControl
{
private PanelPartsViewModel _DC;
public PanelPartsView()
{
InitializeComponent();
_DC = DataContext as PanelPartsViewModel;
}
private void btn_Remove_Click(object sender, RoutedEventArgs e)
{
_DC.Panels.Remove(lb_Panels.SelectedItem as PartsViewModel);
}
private void btn_Add_Click(object sender, RoutedEventArgs e)
{
var pvm = new PartsViewModel();
_DC.Panels.Add(pvm);
lb_Panels.SelectedItem = pvm;
System.Console.WriteLine("lb_Panels.selecteditem = {0}", ((PartsViewModel)lb_Panels.SelectedItem).PanelName);
System.Console.WriteLine("cc_PanelParts.content = {0}", ((PartsViewModel)cc_PanelParts.Content).PanelName);
}
}
mwvm
class mwvm
{
private ObservableCollection<ucvm> _UCs = new ObservableCollection<ucvm>();
public ObservableCollection<ucvm> UCs
{
get { return _UCs; }
}
public mwvm()
{
//this is for for testing, the real application would be purely dynamic
_UCs.Add(new ucvm());
_UCs.Add(new ucvm());
_UCs.Add(new ucvm());
}
}
uc.xaml
<UserControl
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:WpfApplication1" x:Class="WpfApplication1.uc"
mc:Ignorable="d" d:DesignWidth="300" Height="90">
<Grid>
<Grid.DataContext>
<local:ucvm/>
</Grid.DataContext>
<Button Content="{Binding CoolText}" Margin="10,10,10,0" Height="44" VerticalAlignment="Top"/>
<TextBox Height="23" Margin="10,59,10,0" TextWrapping="Wrap" Text="{Binding CoolText}" VerticalAlignment="Top"/>
</Grid>
</UserControl>
uc.xaml.cs
public partial class uc : UserControl
{
public uc()
{
InitializeComponent();
}
}
ucvm.cs
class ucvm : INotifyPropertyChanged
{
private static int i = 1;
private string _CoolText = "<" + i++ + ">" + System.DateTime.Now.ToLongTimeString();
public string CoolText
{
get { return _CoolText; }
set
{
_CoolText = value;
NPC("CoolText");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NPC(string s)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(s));
}
}
私もそのようにコンテンツコントロールをバインドしようとしました...
<ContentControl Content="{Binding SelectedUCVMl, Mode=OneWay}"/>
<ListBox x:Name="lb_UCs" ItemsSource="{Binding UCs}" SelectedItem="{Binding SelectedUCVM}" DisplayMemberPath="CoolText"/>
...など...
<ContentControl Content="{Binding UCs/}"/>
<ListBox x:Name="lb_UCs" ItemsSource="{Binding UCs}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="CoolText"/>
しかし、役に立たない。
どんな助けでも大歓迎です。