Łuk*_*rak 20 data-binding validation wpf mvvm
当我选择(通过单击或通过键盘)我的DataGrid上的空行(当我想添加新行时),出现意外的验证错误(但没有例外) - datagrid的边框变为红色,如您所见下面的图片.当我在空行上第二次点击时,红色边框消失.其他一切工作正常,新行添加.此外,我没有任何验证规则.当我用空文本创建一行时,value是有效的.
我不希望这种行为和这个红色边框,任何人都知道,为什么会发生这种情况以及如何解决这个问题?某些验证失败的原因和地点?

下面我附上一些源代码:
xaml中的DataGrid定义:
<DataGrid IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"
ItemsSource="{Binding Path=ConfigFiles}" SelectedItem="{Binding Path=SelectedConfigFile}"
Grid.Column="1" Height="87" Margin="0,26,11,32" Style="{DynamicResource DataGridStyle}">
<DataGrid.Columns>
<DataGridTextColumn Width="1*" Binding="{Binding Name}" />
</DataGrid.Columns>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
我的ViewModel的部分:
public class ManageModulesVM : BaseVM // Implements INotifyPropertyChanged
{
// ...
public ObservableCollection<ConfigFile> ConfigFiles
{
get { return selectedModule == null ? null : selectedModule.ConfigFiles; }
set
{
selectedModule.ConfigFiles = value;
OnPropertyChanged(() => ConfigFiles);
}
}
public ConfigFile SelectedConfigFile
{
get { return selectedModule == null ? null : selectedModule.SelectedConfigFile; }
set
{
if (value != null)
{
selectedModule.SelectedConfigFile = value;
}
OnPropertyChanged(() => SelectedConfigFile);
OnPropertyChanged(() => Parameters);
}
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
ConfigFile类:
public class ConfigFile
{
public string Name { get; set; }
public IList<Parameter> Parameters { get; set; }
public ConfigFile() { Name = ""; Parameters = new List<Parameter>(); }
}
Run Code Online (Sandbox Code Playgroud)
编辑:进一步调查后我知道,SelectedItem绑定导致问题(当我删除此绑定时,验证错误停止出现),但我仍然不知道为什么以及如何解决这个问题.
Łuk*_*rak 22
我找到了自己的解决方案来解决这个问题.我写了一个值转换器并将其绑定到绑定:
(SelectedItem="{Binding Path=SelectedConfigFile,Converter={StaticResource configFileConverter}}")
转换器类:
namespace Converters
{
public class SelectedConfigFileConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is ConfigFile)
return value;
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在resources.xaml文件(或任何其他资源位置)中定义资源:
<ResourceDictionary (...) xmlns:conv="clr-namespace:Converters" >
<conv:SelectedConfigFileConverter x:Key="configFileConverter" />
</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)
此解决方案的优点是SelectedConfigFile属性的类型没有改变(对于一般object类型),因此它仍然是强类型的.
为了解决这个问题,在Debug模式下单击DataGrid的新行时,请参阅调试窗口.首先会有一些异常消息可以让您了解问题发生的原因.
是的,问题来自于类型转换.您需要将SelectedItem的类型修改为对象类型,如下所示.
public class ManageModulesVM : BaseVM // Implements INotifyPropertyChanged
{
// ...
public object SelectedConfigFile
{
get { return selectedModule == null ? null : selectedModule.SelectedConfigFile; }
set
{
if (value != null)
{
selectedModule.SelectedConfigFile = value;
}
OnPropertyChanged(() => SelectedConfigFile);
OnPropertyChanged(() => Parameters);
}
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
这是一个通用转换器,可以用于任何DataGrid,绑定任何类型的项目:
public class DataGridItemConverter : MarkupExtension, IValueConverter
{
static DataGridItemConverter converter;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value != null && value.GetType() == targetType) ? value : null;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (converter == null)
converter = new DataGridItemConverter();
return converter;
}
}
Run Code Online (Sandbox Code Playgroud)
由于它实现了MarkupExtension,您甚至不需要定义静态资源,您可以像这样引用它:
SelectedItem="{Binding SelectedThing,Converter={conv:DataGridItemConverter}}"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9466 次 |
| 最近记录: |