У меня есть код ниже, который является упрощенным примером того, что я пытаюсь сделать. Я использую конвертер, чтобы попытаться заполнить DataGrid данными из модели, которая у меня есть. DataGrid заполняется правильно, но любые изменения в сетке не сохраняются обратно к объектам. Я указал режим как TwoWay. Когда я ставлю точку останова на конвертер ConvertBack, он никогда не вызывается.WPF IValueConverter.ConvertBack не называется
Я довольно новичок в WPF и MVVM, поэтому не вижу, что я делаю неправильно. Я не могу сделать, чтобы изменить модель, поэтому я хотел бы посмотреть, может ли это работать, если не существует явно превосходного метода.
XAML:
<Window x:Class="SampleBindingProblem.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SampleBindingProblem"
Title="MainWindow" Height="400" Width="500">
<Window.Resources>
<ResourceDictionary>
<local:ScenarioDataTableConverter x:Key="ScenarioDataTableConverter" />
</ResourceDictionary>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Scenarios}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataGrid Margin="5" ItemsSource="{Binding Path=Options, Mode=TwoWay, Converter={StaticResource ScenarioDataTableConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
</Grid>
</Window>
App.xaml.cs:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace SampleBindingProblem
{
public class ColumnInfo
{
public static readonly String[] ColumnLabels = new String[] { "Variable1", "Variable2", "Variable3", "Variable4", "Variable5" };
}
public class ScenarioOption
{
public String Label { get; set; }
public String[] Variables { get; set; }
}
public class Scenario
{
public ScenarioOption[] Options { get; set; }
}
internal class ScenarioDataTableConverter : IValueConverter
{
public Object Convert (Object value, Type targetType, Object parameter, CultureInfo culture)
{
if (value == null)
return (null);
ScenarioOption[] options = (ScenarioOption[]) value;
DataTable table = new DataTable();
table.Columns.Add("Label", typeof(String));
for (Int32 c = 0; c < ColumnInfo.ColumnLabels.Length; ++c)
table.Columns.Add(ColumnInfo.ColumnLabels[c], typeof(String));
foreach (ScenarioOption option in options)
{
DataRow row = table.NewRow();
List<String> lst = new List<String>();
lst.Add(option.Label);
lst.AddRange(option.Variables);
row.ItemArray = lst.ToArray();
table.Rows.Add(row);
}
return (table.DefaultView);
}
public Object ConvertBack (Object value, Type targetType, Object parameter, CultureInfo culture)
{
return (null);
}
}
internal class ViewModel : INotifyPropertyChanged
{
public void RaisePropertyChanged (String property)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged = null;
public ObservableCollection<Scenario> Scenarios { get; set; }
public ViewModel()
{
Scenario s1 = new Scenario();
s1.Options = new ScenarioOption[] {
new ScenarioOption() { Label = "Opt1", Variables=new String[] { "1", "2", "3", "4", "5" } },
new ScenarioOption() { Label = "Opt2", Variables=new String[] { "2", "3", "4", "5", "6" } },
new ScenarioOption() { Label = "Opt3", Variables=new String[] { "3", "4", "5", "6", "7" } },
};
Scenario s2 = new Scenario();
s2.Options = new ScenarioOption[] {
new ScenarioOption() { Label = "Opt1", Variables=new String[] { "1", "2", "3", "4", "5" } },
new ScenarioOption() { Label = "Opt2", Variables=new String[] { "2", "3", "4", "5", "6" } },
new ScenarioOption() { Label = "Opt3", Variables=new String[] { "3", "4", "5", "6", "7" } },
};
this.Scenarios = new ObservableCollection<Scenario>();
this.Scenarios.Add(s1);
this.Scenarios.Add(s2);
}
}
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private void Application_Startup (Object sender, StartupEventArgs e)
{
MainWindow window = new MainWindow();
window.DataContext = new ViewModel();
window.ShowDialog();
}
}
}
Метод ConvertBack() в настоящее время возвращает null, потому что я его не реализовал, так как он до сих пор не был вызван. –