Im very new to the WPF and MVVM (this is my 1st project in WPF). The project I'm working on is supposed to accept some search criteria, and display the results in the grid. To construct the query I'm using Dynamic LINQ queries. I seem to have issues managing instances of my ProjectSearchViewModel which corresponds to the view that's responsible for collecting the search criteria and executing the query. One instance is created when I create MainWindowViewModel. This creates all other viewmodel instances. This is what I expect. But when time comes to Show the MainWindow, I get another ProjectSearchViewModel, I guess from the binding.
The general idea is this:
The search criteria are filled in the ProjectSearchView.
When Load Command is pressed, I send SearchResultMessage using Reactive Extensions method.
The message is picked up by MainWindowViewModel
MainWindowViewModel is querying the ProjectSearchViewModel.SearchResult and assigning the IObservable List to AllProjectsViewModel.AllProjects which is bound to a datagrid to show the results (AllProjectView is responsible to show the grid with resulting projects list)
The problem is that the parameter filling and sending of the SearchResultMessage happens in one instance of ProjectSearchViewModel and the actual querying of SearchResult from MainWindowViewModel happens in another instance, where all the search criteria are empty.
I guess I have no choice but to post my code: Here it the abridged version of it, omitting some iDisposable plumbing and such. For my model I use Entity Framework 4.
As I mentioned, I'm a total newbie so If anyone sees any blatant disregard for common sense, please set me straight.
Imports Cheminator.ViewModel
Partial Public Class App
Inherits Application
Private viewModel As MainWindowViewModel
Private window As MainWindow
Protected Overrides Sub OnStartup(ByVal e As StartupEventArgs)
MyBase.OnStartup(e)
window = New MainWindow
viewModel = New MainWindowViewModel '1st instance of ProjectSearchViewModel created Here
window.DataContext = viewModel
window.Show() '2nd instance of ProjectSearchViewModel created Here
End Sub
End Class
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Cheminator"
xmlns:vm="clr-namespace:Cheminator.ViewModel"
xmlns:vw="clr-namespace:Cheminator.Views"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxd="http://schemas.devexpress.com/winfx/2008/xaml/docking"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dxnb="http://schemas.devexpress.com/winfx/2008/xaml/navbar"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
Title="DXWpfApplication" Height="600" Width="800"
dx:ThemeManager.ThemeName="Office2007Blue"
>
<Window.Resources>
<ResourceDictionary Source="MainWindowResources.xaml" />
</Window.Resources>
<dxd:DockLayoutManager>
<dxd:LayoutGroup>
<dxd:LayoutGroup Orientation="Vertical" Width="3*">
<dxd:DocumentGroup Height="3*" SelectedTabIndex="0">
<dxd:DocumentPanel Caption="Document1" Height="3*" >
开发者_开发百科 <ContentControl
Content="{Binding Path=ProjectsVM}"
/>
</dxd:DocumentPanel>
</dxd:DocumentGroup>
<dxd:LayoutPanel Caption="Search Criteria" Height="*" CaptionImage="Images/Icons/DetailView.png">
<ContentControl
Content="{Binding Path=ProjectsSearchVM}"
/>
</dxd:LayoutPanel>
</dxd:LayoutGroup>
</dxd:LayoutGroup>
</dxd:DockLayoutManager>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Cheminator"
xmlns:vm="clr-namespace:Cheminator.ViewModel"
xmlns:vw="clr-namespace:Cheminator.Views" >
<DataTemplate DataType="{x:Type vm:AllProjectsViewModel}">
<vw:AllProjectsView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ProjectSearchViewModel}">
<vw:ProjectSearchView />
</DataTemplate>
<UserControl x:Class="Cheminator.Views.AllProjectsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxd="http://schemas.devexpress.com/winfx/2008/xaml/docking"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:Cheminator.ViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<dxg:GridControl AutoPopulateColumns="True" ShowBorder="False" >
<dxg:GridControl.DataSource>
<Binding Path="AllProjects"/>
</dxg:GridControl.DataSource>
<dxg:GridControl.View>
<dxg:TableView>
</dxg:TableView>
</dxg:GridControl.View>
</dxg:GridControl>
</UserControl>
<UserControl x:Class="Cheminator.Views.ProjectSearchView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Cheminator.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="160" d:DesignWidth="470">
<Grid Height="160" Width="470">
<Grid.DataContext>
<vm:ProjectSearchViewModel />
</Grid.DataContext>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="175*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Content="Cotation ID:" Height="28" Margin="49,12,32,0" Name="Label1" VerticalAlignment="Top" />
<TextBox Grid.Column="1" Height="23" Margin="0,14,159,0" Name="CotationIDTextBox" VerticalAlignment="Top" Text="{Binding Path=CotationID, UpdateSourceTrigger=LostFocus}"/>
<Label Grid.Row="1" Content="Cotation Name:" Height="28" Margin="49,6,6,0" Name="Label2" VerticalAlignment="Top" />
<TextBox Grid.Row="1" Grid.Column="1" Height="23" Margin="0,8,159,0" Name="CotationNameTextBox" VerticalAlignment="Top" Text="{Binding Path=ProjectSummary, UpdateSourceTrigger=PropertyChanged}"/>
<Label Grid.Row="2" Content="User:" Height="28" Margin="49,6,32,0" Name="Label3" VerticalAlignment="Top" />
<TextBox Grid.Row="2" Grid.Column="1" Height="23" Margin="0,8,159,0" Name="UserTextBox" VerticalAlignment="Top" Text="{Binding Path=UserName, UpdateSourceTrigger=PropertyChanged}"/>
<Button
Command="{Binding Path=LoadCommand}"
Content="_Load"
HorizontalAlignment="Right"
Margin="0,10,51,12"
MinWidth="60" Grid.Row="3" Width="72" Grid.Column="1" />
</Grid>
</UserControl>
Public Class MainWindowViewModel
Inherits ViewModelBase
Private _commands As ReadOnlyCollection(Of CommandViewModel)
Private _ProjectsVM As AllProjectsViewModel
Private _ProjectsSearchVM As ProjectSearchViewModel
Public Sub New()
MyBase.DisplayName = "Cheminator"
_ProjectsSearchVM = New ProjectSearchViewModel
Messenger.[Default].OfType(Of SearchResultMessage) _
.Subscribe(Sub(param As SearchResultMessage)
ProjectsVM.AllProjects = ProjectsSearchVM.SearchResult
End Sub)
_ProjectsVM = New AllProjectsViewModel
End Sub
Public ReadOnly Property ProjectsVM As AllProjectsViewModel
Get
If (_ProjectsVM IsNot Nothing) Then
Return _ProjectsVM
End If
Return Nothing
End Get
End Property
Public ReadOnly Property ProjectsSearchVM As ProjectSearchViewModel
Get
If (_ProjectsSearchVM IsNot Nothing) Then
Return _ProjectsSearchVM
End If
Return Nothing
End Get
End Property
End Class
Public Class AllProjectsViewModel
Inherits ViewModelBase
Private m_ProjectsList As ObservableCollection(Of xGMV_Cotation)
Public Sub New()
MyBase.DisplayName = "Temp AllProjectsViewModel Name" 'Strings.AllProjectsViewModel_DisplayName
End Sub
Public Property AllProjects() As ObservableCollection(Of xGMV_Cotation)
Get
Return m_ProjectsList
End Get
Set(ByVal value As ObservableCollection(Of xGMV_Cotation))
m_ProjectsList = value
OnPropertyChanged("AllProjects")
End Set
End Property
End Class
Public Class ProjectSearchViewModel
Inherits ViewModelBase
Private m_ProjectsList As ObservableCollection(Of xGMV_Cotation)
Public Sub New()
MyBase.DisplayName = "Cheminator.ProjectSearchViewModel"
End Sub
Dim _CotationID As Integer
Public Property CotationID As Integer
Get
Return _CotationID
End Get
Set(ByVal value As Integer)
_CotationID = value
MyBase.OnPropertyChanged("CotationID")
End Set
End Property
Public Property ProjectSummary As String
Public Property UserName As String
Private m_LoadCommand As RelayCommand
Public ReadOnly Property LoadCommand As ICommand
Get
If m_LoadCommand Is Nothing Then
Dim LoadAction As New Action(Of Object)(AddressOf Me.Load)
m_LoadCommand = New RelayCommand(LoadAction)
End If
Return m_LoadCommand
End Get
End Property
Public ReadOnly Property SearchResult() As ObservableCollection(Of xGMV_Cotation)
Get
Dim xWhere As String = ""
Dim i As Integer = 0
Dim parameterList As New ArrayList
If Not String.IsNullOrEmpty(CotationID) Then
xWhere = String.Format("CotationID = @{0}", i)
parameterList.Add(CotationID)
i += 1
End If
If Not String.IsNullOrEmpty(ProjectSummary) Then
If i > 0 Then
xWhere = xWhere & " AND "
End If
xWhere = xWhere & String.Format("ProjectSummary = '@{0}'", i)
i += 1
parameterList.Add(ProjectSummary)
End If
If Not String.IsNullOrEmpty(UserName) Then
If i > 0 Then
xWhere = xWhere & " AND "
End If
xWhere = xWhere & String.Format("UserName = '@{0}'", i)
i += 1
parameterList.Add(UserName)
End If
Return New ObservableCollection(Of xGMV_Cotation)(DataContext.DBEntities.xGMV_Cotations.Where(xWhere, parameterList.ToArray))
End Get
End Property
Private Sub Load()
OnPropertyChanged("SearchResult")
Messenger.Default.Send(New SearchResultMessage())
End Sub
End Class
everytime you create a ProjectSearchView usercontrol, you also create a ProjectSearchViewModel too. you should remove the following from your usercontrl xaml.
<Grid.DataContext>
<vm:ProjectSearchViewModel />
</Grid.DataContext>
because of your datatemplate you do not need to set the datacontext for ProjectSearchView, it already has the right datacontext.
精彩评论