Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF中使用MVVM的嵌套数据绑定不起作用_C#_Wpf_Entity Framework_Mvvm - Fatal编程技术网

C# WPF中使用MVVM的嵌套数据绑定不起作用

C# WPF中使用MVVM的嵌套数据绑定不起作用,c#,wpf,entity-framework,mvvm,C#,Wpf,Entity Framework,Mvvm,我无法理解为什么WPF中的第三个嵌套数据绑定不起作用。我正在使用实体框架和Sql Server 2012,以下是我的实体。一个应用程序可以有多个帐户。有一个Accounts表和一个Applications表 实体 1.应用程序 2.帐目 视图模型 1.应用程序视图模型 2.ApplicationViewModel 3.AccountListViewModel 4.AccountViewModel class ApplicationViewModel : ViewModelBase {

我无法理解为什么WPF中的第三个嵌套数据绑定不起作用。我正在使用实体框架和Sql Server 2012,以下是我的实体。一个应用程序可以有多个帐户。有一个Accounts表和一个Applications表

实体
1.应用程序
2.帐目

视图模型
1.应用程序视图模型
2.ApplicationViewModel
3.AccountListViewModel
4.AccountViewModel

class ApplicationViewModel : ViewModelBase
    {
        private myEntities context = new myEntities();
        private ApplicationViewModel originalValue;

        public ApplicationViewModel()
        {

        }
        public ApplicationViewModel(Application acc)
        {
            //Initialize property values
            this.originalValue = (ApplicationViewModel)this.MemberwiseClone();
        }
        public ApplicationListViewModel Container
        {
            get { return ApplicationListViewModel.Instance(); }
        }

        private AccountListViewModel _AccountLVM = null;

        public AccountListViewModel AccountLVM
        {
            get
            {
                return GetAccounts(); 
            }
            set
            {
                _AccountLVM = value;
                OnPropertyChanged("AccountLVM");
            }
        }
        internal AccountListViewModel GetAccounts()
        {
            _AccountLVM = new AccountListViewModel();
            _AccountLVM.AccountList.Clear();
            foreach (Account i in context.Accounts.Where(x=> x.ApplicationId == this.Id))
            {
               AccountViewModel account = new AccountViewModel(i);
                account.Application = this;
                _AccountLVM.AccountList.Add(account);
            }
            return _AccountLVM;
        }


    }
在我的usercontrol中,我尝试执行以下操作:
1.使用组合框选择使用ApplicationListViewModel(正在工作的应用程序)
2.在选择应用程序后,显示datagrid中的所有帐户(正在工作
3.选定帐户时,显示特定帐户的详细信息。(不显示选定帐户的详细信息。

AccountListViewModel

class ApplicationListViewModel : ViewModelBase
    {
         myEntities context = new myEntities();
        private static ApplicationListViewModel instance = null;

        private ObservableCollection<ApplicationViewModel> _ApplicationList = null;

        public ObservableCollection<ApplicationViewModel> ApplicationList
        {
            get 
            {
                return GetApplications(); 
            }
            set {
                _ApplicationList = value;
                OnPropertyChanged("ApplicationList");
            }
        }

        //public ObservableCollection<ApplicationViewModel> Cu
        private ApplicationViewModel selectedApplication = null;

        public  ApplicationViewModel SelectedApplication
        {
            get
            {
                return selectedApplication;
            }
            set
            {
                selectedApplication = value;
                OnPropertyChanged("SelectedApplication");
            }
        }


        //private ICommand showAddCommand;

        public ApplicationListViewModel()
        {
            this._ApplicationList = GetApplications();
        }

        internal ObservableCollection<ApplicationViewModel> GetApplications()
        {
            if (_ApplicationList == null)
                _ApplicationList = new ObservableCollection<ApplicationViewModel>();
            _ApplicationList.Clear();
            foreach (Application item in context.Applications)
            {
                ApplicationViewModel a = new ApplicationViewModel(item);
                _ApplicationList.Add(a);
            }
            return _ApplicationList;
        }

        public static ApplicationListViewModel Instance()
        {
            if (instance == null)
                instance = new ApplicationListViewModel();
            return instance;
        }
    }
class AccountListViewModel : ViewModelBase
    {
        myEntities context = new myEntities();
        private static AccountListViewModel instance = null;

        private ObservableCollection<AccountViewModel> _accountList = null;

        public ObservableCollection<AccountViewModel> AccountList
        {
            get 
            {
                if (_accountList != null)
                    return _accountList;
                else
                    return GetAccounts(); 
            }
            set {
                _accountList = value;
                OnPropertyChanged("AccountList");
            }
        }
        private AccountViewModel selectedAccount = null;

        public  AccountViewModel SelectedAccount
        {
            get
            {
                return selectedAccount;
            }
            set
            {
                selectedAccount = value;
                OnPropertyChanged("SelectedAccount");
            }
        }
        public AccountListViewModel()
        {
            this._accountList = GetAccounts();
        }

        internal ObservableCollection<AccountViewModel> GetAccounts()
        {
            if (_accountList == null)
                _accountList = new ObservableCollection<AccountViewModel>();
            _accountList.Clear();
            foreach (Account item in context.Accounts)
            {
                AccountViewModel a = new AccountViewModel(item);
                _accountList.Add(a);
            }
            return _accountList;
        }

        public static AccountListViewModel Instance()
        {
            if (instance == null)
                instance = new AccountListViewModel();
            return instance;
        }
}
编辑1:
当我绑定数据以查看所选Account with textbox的详细信息时,它不会显示任何文本。
1.能够将到ApplicationListViewModel的数据绑定到Combobox。
2.成功绑定到基于所选应用程序的查看帐户列表
3。无法绑定到AccountListViewModel中的SelectedAccount。

<UserControl.Resources>
    <vm:ApplicationListViewModel x:Key="AppList" />
</UserControl.Resources>

<StackPanel DataContext="{Binding Source={StaticResource AppList}}">
    <Grid>
        <Grid.RowDefinitions>
            ...
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Row="0" Grid.Column="0">
            <GroupBox Header="View all">
                <StackPanel>
                    <!-- All Applications List -->
                    <ComboBox x:Name="cbxApplicationList"
                              ItemsSource="{Binding Path=ApplicationList}"
                              DisplayMemberPath="Title" SelectedValuePath="Id"
                              SelectedItem="{Binding Path=SelectedApplication, Mode=TwoWay}" 
                              IsSynchronizedWithCurrentItem="True" />

                    <!-- Selected Application Accounts -->
                    <DataGrid x:Name="dtgAccounts" Height="Auto" Width="auto" AutoGenerateColumns="False" 
                              DataContext="{Binding SelectedApplication.AccountLVM}"
                              ItemsSource="{Binding Path=AccountList}" 
                              SelectedItem="{Binding SelectedAccount, Mode=TwoWay}" IsSynchronizedWithCurrentItem="True">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="Title" Binding="{Binding Path=Title}"></DataGridTextColumn>
                        </DataGrid.Columns>
                    </DataGrid>
                </StackPanel>
            </GroupBox>
        </StackPanel>

        <StackPanel Grid.Row="0" Grid.Column="1" >
            <GroupBox x:Name="grpBoxAccountDetails" Header="New Account" >
                <!-- Selected Account Details -->
                <!-- DataContext binding does not appear to work -->
                <StackPanel DataContext="{Binding SelectedApplication.AccountLVM.SelectedAccount}"  >
                    <Grid>
                        <Grid.RowDefinitions>
                            ...
                        </Grid.ColumnDefinitions>
                        <TextBlock x:Name="lblApplication" Grid.Row="0" Grid.Column="0" >Application</TextBlock>
                        <ComboBox x:Name="cbxApplication" Grid.Row="0" Grid.Column="1" 
                                  DataContext="{Binding Source={StaticResource AppList}}" 
                                  ItemsSource="{Binding ApplicationList}" 
                                  DisplayMemberPath="Title" SelectedValuePath="Id" 
                                  SelectedValue="{Binding SelectedApplication.AccountLVM.SelectedAccount.ApplicationId}">
                        </ComboBox>
                        <TextBlock x:Name="lblTitle" Grid.Row="0" Grid.Column="0" >Title</TextBlock>
                        <TextBox x:Name="txtTitle" Grid.Row="0" Grid.Column="1" Height="30" Width="200" 
                                Text="{Binding Title}" DataContext="{Binding Mode=OneWay}"></TextBox>
                        <Button Grid.Row="1" Grid.Column="0" Command="{Binding AddAccount}">Add</Button>
                    </Grid>
                </StackPanel>
            </GroupBox>
        </StackPanel>
    </Grid>
</StackPanel>
<UserControl.Resources>
    <vm:AccountsViewModel x:Key="ALVModel" />
</UserControl.Resources>
<StackPanel DataContext="{Binding Source={StaticResource ALVModel}}" Margin="0,0,-390,-29">
    <StackPanel>
        <ComboBox x:Name="cbxApplicationList"
                  ItemsSource="{Binding Path=ApplicationList}"
                  DisplayMemberPath="Title" SelectedValuePath="Id"
                  SelectedItem="{Binding Path=SelectedApplication, Mode=TwoWay}" 
                  IsSynchronizedWithCurrentItem="True"></ComboBox>
        <DataGrid x:Name="dtgAccounts" Height="Auto" Width="auto" 
                  AutoGenerateColumns="False" 
                  ItemsSource="{Binding Path=AccountList}" 
                  SelectedItem="{Binding SelectedAccount, Mode=TwoWay}" 
                  IsSynchronizedWithCurrentItem="True" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Title" Binding="{Binding Path=Title}"></DataGridTextColumn>
                <DataGridTextColumn Header="CreatedDate" Binding="{Binding Path=CreatedDate}"></DataGridTextColumn>
                <DataGridTextColumn Header="LastModified" Binding="{Binding Path=LastModifiedDate}"></DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
    <StackPanel Height="Auto" Width="300" HorizontalAlignment="Left" DataContext="{Binding Path=SelectedAccount}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="30"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"></ColumnDefinition>
                <ColumnDefinition Width="200"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBlock x:Name="lblTitle" Grid.Row="0" Grid.Column="0" >Title</TextBlock>
            <TextBox x:Name="txtTitle"   Grid.Row="0" Grid.Column="1" Height="30" Width="200" 
                     Text="{Binding Title}"></TextBox>
        </Grid>
    </StackPanel>
</StackPanel>
我认为在下一行中,它不会显示所选帐户的任何详细信息。我已经检查了所有数据绑定语法。在属性中,我可以查看适当的DataContext并绑定到属性。但是它没有显示任何文本。当我在DataGrid中选择每个单独的记录时,我能够调试调用并选择对象,但不知何故,该对象没有显示在最后的文本框中

DataContext="{Binding SelectedApplication.AccountLVM.SelectedAccount}"
Edit2:
根据下面评论中的建议,我尝试了snoop,并且能够看到标题文本框行以红色突出显示。我正在尝试更改绑定路径属性和datacontext,但仍然不起作用。当我试图点击“Delve绑定表达式”时,它给了我一个未处理的异常。我不知道这是什么意思,如果它来自史努比

Edit3:
我已经为Account Details部分的StackPanel和textbox的text属性截图了DataContext属性

解决方案:
根据下面的建议,我对我的解决方案做了以下修改,使其更加简单。我把它弄得太复杂了。
1.AccountsViewModel
2.AccountViewModel
3.应用程序视图模型

class ApplicationViewModel : ViewModelBase
    {
        private myEntities context = new myEntities();
        private ApplicationViewModel originalValue;

        public ApplicationViewModel()
        {

        }
        public ApplicationViewModel(Application acc)
        {
            //Initialize property values
            this.originalValue = (ApplicationViewModel)this.MemberwiseClone();
        }
        public ApplicationListViewModel Container
        {
            get { return ApplicationListViewModel.Instance(); }
        }

        private AccountListViewModel _AccountLVM = null;

        public AccountListViewModel AccountLVM
        {
            get
            {
                return GetAccounts(); 
            }
            set
            {
                _AccountLVM = value;
                OnPropertyChanged("AccountLVM");
            }
        }
        internal AccountListViewModel GetAccounts()
        {
            _AccountLVM = new AccountListViewModel();
            _AccountLVM.AccountList.Clear();
            foreach (Account i in context.Accounts.Where(x=> x.ApplicationId == this.Id))
            {
               AccountViewModel account = new AccountViewModel(i);
                account.Application = this;
                _AccountLVM.AccountList.Add(account);
            }
            return _AccountLVM;
        }


    }
现在,我已经创建了属性,如
SelectedApplication
SelectedAccount
一体式
AccountsViewModel
。删除了所有复杂的DataContext语法,现在xaml页面中只有一个DataContext

简化代码

class AccountsViewModel: ViewModelBase
    {
        myEntities context = new myEntities();

        private ObservableCollection<ApplicationViewModel> _ApplicationList = null;

        public ObservableCollection<ApplicationViewModel> ApplicationList
        {
            get
            {
                if (_ApplicationList == null)
                {
                    GetApplications();
                }
                return _ApplicationList;
            }
            set
            {
                _ApplicationList = value;
                OnPropertyChanged("ApplicationList");
            }
        }
        internal ObservableCollection<ApplicationViewModel> GetApplications()
        {
            if (_ApplicationList == null)
                _ApplicationList = new ObservableCollection<ApplicationViewModel>();
            else
                _ApplicationList.Clear();
            foreach (Application item in context.Applications)
            {
                ApplicationViewModel a = new ApplicationViewModel(item);
                _ApplicationList.Add(a);
            }
            return _ApplicationList;
        }
        //Selected Application Property
        private ApplicationViewModel selectedApplication = null;

        public ApplicationViewModel SelectedApplication
        {
            get
            {
                return selectedApplication;
            }
            set
            {
                selectedApplication = value;
                this.GetAccounts();
                OnPropertyChanged("SelectedApplication");
            }
        }
        private ObservableCollection<AccountViewModel> _accountList = null;

        public ObservableCollection<AccountViewModel> AccountList
        {
            get
            {
                if (_accountList == null)
                    GetAccounts();
                return _accountList;
            }
            set
            {
                _accountList = value;
                OnPropertyChanged("AccountList");
            }
        }

        //public ObservableCollection<AccountViewModel> Cu
        private AccountViewModel selectedAccount = null;

        public AccountViewModel SelectedAccount
        {
            get
            {
                return selectedAccount;
            }
            set
            {
                selectedAccount = value;
                OnPropertyChanged("SelectedAccount");
            }
        }
        internal ObservableCollection<AccountViewModel> GetAccounts()
        {
            if (_accountList == null)
                _accountList = new ObservableCollection<AccountViewModel>();
            else
                _accountList.Clear();
            foreach (Account item in context.Accounts.Where(x => x.ApplicationId == this.SelectedApplication.Id))
            {
                AccountViewModel a = new AccountViewModel(item);
                _accountList.Add(a);
            }
            return _accountList;
        }

    }
class AccountsViewModel:ViewModelBase
{
myEntities上下文=新的myEntities();
private observeCollection\u ApplicationList=null;
公共可观察收集应用程序列表
{
得到
{
if(_ApplicationList==null)
{
GetApplications();
}
返回应用程序列表;
}
设置
{
_应用程序列表=值;
OnPropertyChanged(“应用程序列表”);
}
}
内部ObservableCollection GetApplications()
{
if(_ApplicationList==null)
_ApplicationList=新的ObservableCollection();
其他的
_ApplicationList.Clear();
foreach(context.Applications中的应用程序项)
{
ApplicationViewModel a=新的ApplicationViewModel(项目);
_应用程序列表。添加(a);
}
返回应用程序列表;
}
//选定的应用程序属性
私有应用程序ViewModel selectedApplication=null;
公共应用程序视图模型选定的应用程序
{
得到
{
返回所选的应用程序;
}
设置
{
selectedApplication=值;
这个.GetAccounts();
OnPropertyChanged(“SelectedApplication”);
}
}
私有ObservableCollection\u accountList=null;
公共可观测集合帐户列表
{
得到
{
如果(_accountList==null)
GetAccounts();
返回账户列表;
}
设置
{
_accountList=值;
OnPropertyChanged(“会计清单”);
}
}
//公共可观测收集Cu
private Account ViewModel selectedAccount=null;
公共帐户视图模型所选帐户
{
得到
{
返回所选科目;
}
设置
{
selectedAccount=值;
已更改的不动产(“选定账户”);
}
}
内部ObservableCollection GetAccounts()
{
如果(_accountList==null)
_accountList=新的ObservableCollection();
其他的
_accountList.Clear();
foreach(context.Accounts.Where(x=>x.ApplicationId==this.SelectedApplication.Id)中的帐户项)
{
AccountViewModel a=新的AccountViewModel(项目);
_会计清单。添加(a);
}
返回账户列表;
}
}
XAML侧

<UserControl.Resources>
    <vm:ApplicationListViewModel x:Key="AppList" />
</UserControl.Resources>

<StackPanel DataContext="{Binding Source={StaticResource AppList}}">
    <Grid>
        <Grid.RowDefinitions>
            ...
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Row="0" Grid.Column="0">
            <GroupBox Header="View all">
                <StackPanel>
                    <!-- All Applications List -->
                    <ComboBox x:Name="cbxApplicationList"
                              ItemsSource="{Binding Path=ApplicationList}"
                              DisplayMemberPath="Title" SelectedValuePath="Id"
                              SelectedItem="{Binding Path=SelectedApplication, Mode=TwoWay}" 
                              IsSynchronizedWithCurrentItem="True" />

                    <!-- Selected Application Accounts -->
                    <DataGrid x:Name="dtgAccounts" Height="Auto" Width="auto" AutoGenerateColumns="False" 
                              DataContext="{Binding SelectedApplication.AccountLVM}"
                              ItemsSource="{Binding Path=AccountList}" 
                              SelectedItem="{Binding SelectedAccount, Mode=TwoWay}" IsSynchronizedWithCurrentItem="True">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="Title" Binding="{Binding Path=Title}"></DataGridTextColumn>
                        </DataGrid.Columns>
                    </DataGrid>
                </StackPanel>
            </GroupBox>
        </StackPanel>

        <StackPanel Grid.Row="0" Grid.Column="1" >
            <GroupBox x:Name="grpBoxAccountDetails" Header="New Account" >
                <!-- Selected Account Details -->
                <!-- DataContext binding does not appear to work -->
                <StackPanel DataContext="{Binding SelectedApplication.AccountLVM.SelectedAccount}"  >
                    <Grid>
                        <Grid.RowDefinitions>
                            ...
                        </Grid.ColumnDefinitions>
                        <TextBlock x:Name="lblApplication" Grid.Row="0" Grid.Column="0" >Application</TextBlock>
                        <ComboBox x:Name="cbxApplication" Grid.Row="0" Grid.Column="1" 
                                  DataContext="{Binding Source={StaticResource AppList}}" 
                                  ItemsSource="{Binding ApplicationList}" 
                                  DisplayMemberPath="Title" SelectedValuePath="Id" 
                                  SelectedValue="{Binding SelectedApplication.AccountLVM.SelectedAccount.ApplicationId}">
                        </ComboBox>
                        <TextBlock x:Name="lblTitle" Grid.Row="0" Grid.Column="0" >Title</TextBlock>
                        <TextBox x:Name="txtTitle" Grid.Row="0" Grid.Column="1" Height="30" Width="200" 
                                Text="{Binding Title}" DataContext="{Binding Mode=OneWay}"></TextBox>
                        <Button Grid.Row="1" Grid.Column="0" Command="{Binding AddAccount}">Add</Button>
                    </Grid>
                </StackPanel>
            </GroupBox>
        </StackPanel>
    </Grid>
</StackPanel>
<UserControl.Resources>
    <vm:AccountsViewModel x:Key="ALVModel" />
</UserControl.Resources>
<StackPanel DataContext="{Binding Source={StaticResource ALVModel}}" Margin="0,0,-390,-29">
    <StackPanel>
        <ComboBox x:Name="cbxApplicationList"
                  ItemsSource="{Binding Path=ApplicationList}"
                  DisplayMemberPath="Title" SelectedValuePath="Id"
                  SelectedItem="{Binding Path=SelectedApplication, Mode=TwoWay}" 
                  IsSynchronizedWithCurrentItem="True"></ComboBox>
        <DataGrid x:Name="dtgAccounts" Height="Auto" Width="auto" 
                  AutoGenerateColumns="False" 
                  ItemsSource="{Binding Path=AccountList}" 
                  SelectedItem="{Binding SelectedAccount, Mode=TwoWay}" 
                  IsSynchronizedWithCurrentItem="True" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Title" Binding="{Binding Path=Title}"></DataGridTextColumn>
                <DataGridTextColumn Header="CreatedDate" Binding="{Binding Path=CreatedDate}"></DataGridTextColumn>
                <DataGridTextColumn Header="LastModified" Binding="{Binding Path=LastModifiedDate}"></DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
    <StackPanel Height="Auto" Width="300" HorizontalAlignment="Left" DataContext="{Binding Path=SelectedAccount}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="30"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"></ColumnDefinition>
                <ColumnDefinition Width="200"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBlock x:Name="lblTitle" Grid.Row="0" Grid.Column="0" >Title</TextBlock>
            <TextBox x:Name="txtTitle"   Grid.Row="0" Grid.Column="1" Height="30" Width="200" 
                     Text="{Binding Title}"></TextBox>
        </Grid>
    </StackPanel>
</StackPanel>

标题
public AccountListViewModel AccountLVM
{
    get
    {
        if (_accountLVM == null)
            GetAccounts(); // or _accountLVM = GetAccountLVM();

        return _accountLVM;
    }
    set { ... }
}
<TextBox x:Name="txtTitle" ...
         Text="{Binding ElementName=dtgAccounts, Path=SelectedItem.Title}" />
<ComboBox ItemsSource="{Binding ApplicationList}"
          SelectedItem="{Binding SelectedApplication}" />

<DataGrid ItemsSource="{Binding SelectedApplication.Accounts}"
          SelectedItem="{Binding SelectedAccount}" />

<StackPanel DataContext="{Binding SelectedAccount}">
   ...
</StackPanel>