如何解决此XAML绑定错误?

时间:2012-05-17 16:22:55

标签: wpf xaml mvvm

首先是一些背景,可以压缩成编辑VatCodeViewModel的属性VatCode。

我在ViewModel中有一个具有两个特定属性的StockItem:

public class StockItemViewModel : ViewModelBase
{
    private VatCodeViewModel _vatCode;

    public VatCodeViewModel VatCode
    {
        get { return _vatCode; }
        set
        {
            if (_vatCode != value)
            {
                _vatCode = value;
                RaisePropertyChanged("VatCode");
            }
        }
    }
}

VatCode属性接受VatCodeViewModel类型。

为了管理编辑体验,我有一个名为EditStockItemViewModel的ViewModel。这有元数据,如IsDirty,IsNew等,但是Item属性设置为正在编辑的项目 - 在这种情况下是StockItemViewModel的实例。 Item属性位于基类中(TViewModel == StockItemViewModel)......

public class UnMappedEditableViewModelBase<TViewModel> : ViewModelBase
{
    private TViewModel _item;

    public TViewModel Item
    {
        get { return _item; }
        set
        {
            if (_item != value)
            {
                _item = value;
                RaisePropertyChanged("Item");
            }
        }
    }
}

和实现类(EditStockItemViewModel,它具有StockItemViewModel项)...

public class EditStockItemViewModel : UnMappedEditableViewModelBase<StockItemViewModel>
{
        private ObservableCollection<VatCodeViewModel> _vatCodes=new ObservableCollection<VatCodeViewModel>();

    public ObservableCollection<VatCodeViewModel> VatCodes
    {
        get { return _vatCodes; }
        set
        {
            if (_vatCodes != value)
            {
                _vatCodes = value;
                RaisePropertyChanged("VatCodes");
            }
        }
    }


public EditStockItemViewModel()
        :base()
{
        if (IsInDesignMode)
        {
        }
        else
        {
                                RefreshVatCodesList(null); // refreshes VatCodes property


            Save = new RelayCommand(() =>
                {
                                                // save functionality snipped

                }, () =>
            {
                bool canExecute =                        Item.VatCode!=null; // this is ALWAYS null - binding failing
                return canExecute;
            });         
        }
    }


}

因此,ViewModel.Item属性始终是正在编辑的项目。

我的观点片段......

    <TextBlock Text="VAT Code:" Grid.Column="1" Grid.Row="3" Style="{StaticResource ComboHeaderTextBlock}" />
    <telerik:RadComboBox Grid.Column="2" Grid.Row="3" Style="{StaticResource RadComboBox}" Width="300" HorizontalAlignment="Left"
                ItemsSource="{Binding VatCodes}" SelectedValuePath="Item.VatCode" 
                ClearSelectionButtonVisibility="Collapsed"
                CanAutocompleteSelectItems="True"
                CanKeyboardNavigationSelectItems="True"
                IsEditable="False"
                OpenDropDownOnFocus="False"
                IsFilteringEnabled="False"
                EmptyText="Select ...">
        <telerik:RadComboBox.SelectedValue>
            <Binding Path="Item.VatCode" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" RelativeSource="{RelativeSource FindAncestor,AncestorType={x:Type UserControl}}" >
                <Binding.ValidationRules>
                    <DataErrorValidationRule />
                </Binding.ValidationRules>
            </Binding>
        </telerik:RadComboBox.SelectedValue>
        <telerik:RadComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Key}" Style="{StaticResource TextBlock}" />
                    <TextBlock Text="{Binding Name}" Style="{StaticResource DimTextBlock}" />
                    <TextBlock Text="{Binding ActiveRate.Rate}" Margin="5 5 0 5" />
                    <TextBlock Text="%" Margin="0 5 5 5"  />
                </StackPanel>

            </DataTemplate>
        </telerik:RadComboBox.ItemTemplate>
    </telerik:RadComboBox>

所以在这一切结束时,我有:

绑定到[ViewModel] .Item.VatCode并使用[ViewModel] .VatCodes作为源的VatCode。

列表已填充并显示正常。我知道ViewModel绑定正确。

问题是VatCode没有绑定到Item.VatCode属性。所以当我进入Save方法时,Item.VatCode属性为null(即不工作)。

我收到以下绑定错误,似乎是相关的:

  

System.Windows.Data错误:17:无法获取'Item'值(类型   来自''的'String')(类型'VatCodeViewModel')。   BindingExpression:路径= Item.VatCode;的DataItem = 'VatCodeViewModel'   (的HashCode = 27875274); target元素是'RadComboBox'(Name ='');目标   属性是'NoTarget'(类型'对象')   TargetParameterCountException:“System.Reflection.TargetParameterCountException:   参数计数不匹配。

显然错误表明我的绑定表达式Item.VatCode是可疑的,但我不确定如何纠正它。

2 个答案:

答案 0 :(得分:1)

我认为问题出现在你的组合框标记的这一行:

ItemsSource="{Binding VatCodes}" SelectedValuePath="Item.VatCode" 

这表示从 VatCodes (类型 VatCodeViewModel )中提取组合框的项目,对于组合框值,请使用 VatCodeViewModel的属性名为 Item.VatCode 。如果没有看到 VatCodeViewModel 的定义,很难说,但我怀疑该属性不存在。

这就是我认为你的意思。将 SelectedValuePath 设为 VatCodeViewModel 的属性(假设为 VatCode ),然后将选择绑定到 Item.VatCode 。你可以这样做:

ItemsSource="{Binding VatCodes}" SelectedValuePath="VatCode" SelectedValue="{Binding Item.VatCode}"

答案 1 :(得分:0)

发现它,我被文档中提供的示例误导了。我不应该使用路径SelectedValuePath。所以我的新代码是:

 <TextBlock Text="VAT Code:" Grid.Column="1" Grid.Row="3" Style="{StaticResource ComboHeaderTextBlock}" />
        <telerik:RadComboBox Grid.Column="2" Grid.Row="3" Style="{StaticResource RadComboBox}" Width="300" HorizontalAlignment="Left"
                    ItemsSource="{Binding VatCodes}"  
                    ClearSelectionButtonVisibility="Collapsed"
                    CanAutocompleteSelectItems="True"
                    CanKeyboardNavigationSelectItems="True"
                    IsEditable="False"
                    OpenDropDownOnFocus="False"
                    IsFilteringEnabled="False"
                    EmptyText="Select ...">
            <telerik:RadComboBox.SelectedValue>
                <Binding Path="Item.VatCode" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
                    <Binding.ValidationRules>
                        <DataErrorValidationRule />
                    </Binding.ValidationRules>
                </Binding>
            </telerik:RadComboBox.SelectedValue>
            <telerik:RadComboBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Key}" Style="{StaticResource TextBlock}" />
                        <TextBlock Text="{Binding Name}" Style="{StaticResource DimTextBlock}" />
                        <TextBlock Text="{Binding ActiveRate.Rate}" Margin="5 5 0 5" />
                        <TextBlock Text="%" Margin="0 5 5 5"  />
                    </StackPanel>

                </DataTemplate>
            </telerik:RadComboBox.ItemTemplate>
        </telerik:RadComboBox>