wpf主要细节实现两种方式绑定需要路径或XPATH

时间:2013-09-08 19:03:07

标签: c# wpf wpf-controls wpfdatagrid

Allready在主细节架构中有两个类,

master类有一个detail master的集合,需要(想要)内联执行所有原始选项。

课程:

public partial class Items
{
    public Items()
    {
        this.Detail = new HashSet<Detail>();
    }

    public decimal NumIdConcepto { get; set; }
    public string StrDescripcionConcepto { get; set; }

    public virtual ICollection<Detail> Detail { get; set; }
}

public partial class Detail
{
    public int IntTipoAsociado { get; set; }
    public decimal NumIdConcepto { get; set; }

    public virtual Items Items { get; set; }
    public virtual Master Master { get; set; }
}

public partial class Master
{
    public Master()
    {
        this.Detail = new HashSet<Detail>();
    }

    public int IntTipoAsociado { get; set; }
    public string StrDescripcionTipoAsociado { get; set; }

    public virtual ICollection<Detail> Detail { get; set; }
}

出于编辑目的,EF生成器的限制必须执行转换     从 HashSet ObservableCollection ,用于Master的详细信息收集

public class listToObservableCollection : BaseConverter, IValueConverter
{
    public HashSet<Detail> JustForPath { get; set; }
    public ObservableCollection<Detail> JustForPathObservable { get; set; }

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        HashSet<Detail> observableList = (HashSet<Detail>)value;
        JustForPathObservable = new ObservableCollection<Detail>(observableList);
        return JustForPathObservable;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        JustForPath = (HashSet<Detail>)value;
        return JustForPath;
    }
}

public abstract class BaseConverter : MarkupExtension
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}  

使用这种结构我想生成一个DataGrid,它允许我添加,删除和编辑Detail In line,不想调用其他表单

像这样:

enter image description here

我的XAML代码如下所示:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModels="clr-namespace:Contratos.ViewModels" x:Class="Contratos.Views.TipoAsociado"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF45"
    xmlns:l="clr-namespace:Recursos;assembly=Recursos"
    Title="{Binding Title}" Height="Auto" Width="Auto">
<Window.DataContext>
    <ViewModels:TipoAsociadoVM/>
</Window.DataContext>
<Window.Resources>
    <l:listToObservableCollection x:Key="listoToObservable"/>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <DataGrid Grid.Row="1" 
              ItemsSource="{Binding Master}"  
              AutoGenerateColumns="False" 
              SelectionMode="Single"
              GridLinesVisibility="Vertical"
              CanUserAddRows="True"
              CanUserDeleteRows="True"
              x:Name="GridTipoAsociado"
              Margin="5" SelectionChanged="GridTipoAsociado_SelectionChanged">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <cmd:EventToCommand Command="{Binding _ICommandSelectionChange}"
                                    PassEventArgsToCommand="True"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Description" x:Name="Description">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Content="{Binding StrDescripcionTipoAsociado}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding StrDescripcionTipoAsociado }"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
        <DataGrid.RowDetailsTemplate>
            <DataTemplate>
                <DataGrid Grid.Row="1" 
                        ItemsSource="{Binding Path=Detail,Converter={StaticResource listoToObservable},Mode=TwoWay}"
                        DisplayMemberPath="StrDescripcionConcepto"
                        AutoGenerateColumns="False" 
                        IsSynchronizedWithCurrentItem="True"
                        SelectionMode="Single"
                        SelectionUnit="Cell"
                        GridLinesVisibility="Vertical"
                        CanUserAddRows="True"
                        CanUserDeleteRows="True"                            
                        x:Name="GridItems"
                        Margin="20,5,5,5">
                    <DataGrid.Columns>
                        <DataGridTemplateColumn Header="Items">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Label Content="{Binding Items.StrDescripcionConcepto}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                            <DataGridTemplateColumn.CellEditingTemplate>
                                <DataTemplate>
                                    <!--
                                        Here is my problem How can i to bind to the propper values to perform Editing 
                                        Without having this exception "TWO WAY BINDING REQUIRES PATH OR XPATH"  when try to update DETAIL items:
                                    -->     
                                    <TextBox Text="{Binding Items.StrDescripcionConcepto}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellEditingTemplate>
                        </DataGridTemplateColumn>
                    </DataGrid.Columns>
                </DataGrid>
            </DataTemplate>
        </DataGrid.RowDetailsTemplate>
    </DataGrid>
</Grid>
</Window>

现在,我需要有关如何构建一个propper CellEditingTemplate的帮助,允许我编辑我需要的所有更改?

这是我的问题如何绑定到propper值来执行编辑 在尝试更新详细信息项时没有这个例外“两种方式绑定需要路径或XPATH”?

注意:我不想创建新商品,在此处,只需将其附加到明细

2 个答案:

答案 0 :(得分:1)

终于找到了我的问题,当然还有解决方案。

绑定必须相对于窗口的datacontext而不是 relative 到它的父级,在本例中为 DataGrid

我正在重新定义窗口的datacontext作为静态资源,然后我将其重用于需要访问我的模型的全局属性的元素,Grid和CellEditingTemplate

<Window.Resources>
    <ViewModels:ViewModel x:Key="ViewDataContext"/>
</Window.Resources>

<!-- Here I use Static resource as Data context -->
<Grid DataContext="{Binding Source={StaticResource ResourceKey=ViewDataContext}}">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Tipo de asociado" x:Name="TipoUsuarioSeleccionado">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Content="{Binding SomeElement}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                   <DataTemplate>
                     <!-- Again I use Static resource as Data context -->
                     <Grid Height="130" DataContext="{Binding Source={StaticResource ViewDataContext}}">
                           <Grid.RowDefinitions>
                               <RowDefinition Height="Auto"></RowDefinition>
                               <RowDefinition Height="*"></RowDefinition>
                           </Grid.RowDefinitions>
                           <TextBox x:Name="Filtro" Text="{Binding SomeInViewModel}"/>
                           <ListView Grid.Row="1" ItemsSource="{Binding ListaItems}">
                              <ListView.ItemTemplate>
                                  <DataTemplate>
                                     <TextBlock Text="{Binding SomeinVM}"/>
                                  </DataTemplate>
                              </ListView.ItemTemplate>
                           </ListView>
                     </Grid>
                </DataTemplate>
             </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
</Grid>

答案 1 :(得分:0)

如果绑定路径不正确,也可能抛出错误“两个绑定需要路径或XPATH”。例如,如果您的属性名为“DisplayName”,但您在XAML绑定表达式中使用了“Name”。

在这种情况下,如果您正在寻找,还可以在“输出”窗口中从VS调试器获取其他信息。或者,如果像我一样,你不记得去看那里,也许你会花半天时间在互联网上搜索,然后才意识到你做了一个假设,接着是一个错字。

所以在我的情况下,这个错误意味着绑定路径不正确。也许您的路径丢失了,您需要指定它(因此,Binding Path=.Binding建议的丰富程度。或者您可能输错了,需要仔细检查您对属性名称的假设。

具有WPF绑定调试的规则#1。始终保持“输出”窗口处于打开状态。