【问题标题】:Why I get UnsetValue after editing using MultiValueConverter?为什么我在使用 MultiValueConverter 编辑后得到 UnsetValue?
【发布时间】:2014-04-04 17:24:24
【问题描述】:

我有 DataGridDataGridComboBoxColumn 可以编辑的列。当我编辑它时抛出异常。调试后我发现Converter 收到DependencyProperty.UnsetValue,因此我必须通过返回"" 将其过滤掉,这导致显示空单元格。

我试图用谷歌搜索并理解为什么我得到DependencyProperty.UnsetValue 但没有运气。

有什么想法吗?

public UserControl()
{
    InitializeComponent();

    DataContext = new MyViewModel();
}

public class MyViewModel : ViewModelBase
{
    public ObservableCollection<MyItem> MyItems { get; private set; }

    public MyViewModel()
    {           
        LoadStates();
    }

    public void LoadStates()
    {
        MyItems = new ObservableCollection<MyItem>(DataProvider.GetList());

        //...
    }
}

public class MyItem
{
    public bool Start {get; set;}
}


public class BoolToStatusConverter : IMultiValueConverter
{
    private MyViewModel _model;            

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        _model = values[0] as MyViewModel ;
        //TODO: Why I get UnsetValue??
        if (values[1] == DependencyProperty.UnsetValue) return "";

        //Using _model
        //...

        return (bool)values[1] ? Statuses.Start : Statuses.Stop;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        return new object[] { _model, (Statuses)value == Statuses.Start };
    }
}

<UserControl.Resources>
    <local:BoolToStatusConverter x:Key="BoolToStatusConverter" />

    <ObjectDataProvider x:Key="myEnum" MethodName="GetValues" ObjectType="{x:Type core:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type Type="local:Statuses"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>

</UserControl.Resources>

<Grid>
    <DataGrid ItemsSource="{Binding MyItems}" AutoGenerateColumns="False" >
        <DataGrid.Columns>              
            <DataGridComboBoxColumn Header="Status" ItemsSource="{Binding Source={StaticResource myEnum}}">                    
                <DataGridComboBoxColumn.SelectedItemBinding>
                    <MultiBinding Converter="{StaticResource BoolToStatusConverter}">
                        <Binding Path="DataContext"
                                RelativeSource="{RelativeSource AncestorType={x:Type UserControl}}" />
                        <Binding Path="Start" />
                    </MultiBinding>
                </DataGridComboBoxColumn.SelectedItemBinding>
            </DataGridComboBoxColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

【问题讨论】:

  • @EricScherrer,我以前看过这篇文章,但我不明白我错在哪里。你能帮忙吗?
  • 可能是填充数据的时间问题。 MyItems 何时创建?
  • 在它被初始化之后,你会立即发送一个属性更改事件。
  • @EricScherrer,我更新了我的帖子。我添加了如何创建MyViewModel 并填充MyItems。如果您能看一下,我将不胜感激

标签: c# wpf


【解决方案1】:

为什么不直接使用常规的 IValueConverter?我不确定在这种情况下您是否真的需要 IMultiValueConverter。这对我有用:

public class BoolToStatusConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if ((bool) value)
        {
            return Statuses.Start;
        }

        return Statuses.Stop;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var theValue = (Statuses)value;

        if (theValue == Statuses.Start)
        {
            return true;
        }

        return false;
    }
}

还有 XAML:

    <DataGrid ItemsSource="{Binding MyItems}" AutoGenerateColumns="False" >
        <DataGrid.Columns>
            <DataGridComboBoxColumn Header="Status" ItemsSource="{Binding Source={StaticResource myEnum}}">
                <DataGridComboBoxColumn.SelectedItemBinding>
                    <Binding Converter="{StaticResource BoolToStatusConverter}" Path="Start">
                    </Binding>
                </DataGridComboBoxColumn.SelectedItemBinding>
            </DataGridComboBoxColumn>
        </DataGrid.Columns>
    </DataGrid>

另外,为了进一步简化,只需将 MyItem 中的 Start 字段设置为 Statuses,然后完全松开转换器。

【讨论】:

  • 我需要将我的 ViewModel 传递给转换器,并根据它的其他属性来决定是将其转换为 Start 还是 Stop。虽然,在写这篇文章时,我认为这应该是 ViewModel 本身的责任,不是吗?无论如何,如果我确实想将 ViewModel 传递给 Converter,那我该怎么做呢?
  • 看起来你几乎拥有它。在开始搞砸之前,我确实看到了 UnsetValue 行为,但我不确定它为什么会这样做。不过我同意,ViewModel 或它所组成的对象应该封装 Start 的值的逻辑。
  • FWIW - 如果您想使用多重绑定获得该视图模型,问题是您需要将 FindAncestor 添加到您的 RelativeSource,如下所示:RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl }}
  • ...并进一步查看它,添加 FindAncestor 将使值 [0] 的 UnsetValue 问题消失,但您仍然必须处理值 [1] 的问题。
  • 其实我对 values[0] 没有问题,只是对 values[1] 有问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-21
  • 1970-01-01
  • 2019-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-04
相关资源
最近更新 更多