问题
I have created a reorder application. As storage I am using a MongoDB server. I want to carry out CRUD operations by clicking buttons in my main view. The create operation is already running smoothly. Now I am trying to get the READ (QUERY) operation done.
My MongoDB collection
reorders
has the following structure:
The most important part here is the "artikelliste"-key because it inherits all the key value pairs of my 2nd collection
articles
as you can see in the next structure(NOTE THAT THE OBJECT IDs ARE THE ONLY CONNECTION POINT!):
I created 2 datagrids like this:
The first datagrid should contain the values of my collection REORDERS without the array artikelliste. The second datagrid should contain the values of my collection ARTICLES but only those related to the corresponding reorder...
What that means is if I click in the first row of the REORDERS datagrid I want the 2nd datagrid to show only the articles that are connected with this reorder - through an object-id join (because the object-id is the only value that connects these 2 collections!).
What I did so far... XAML
<Window x:Class="Nachbestellungen.vorhandeneNachbestellungen"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Nachbestellungen"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Title="Vorhandene Nachbestellungen" WindowState="Maximized" WindowStyle="ThreeDBorderWindow">
<Window.Resources>
<Style x:Key="cellLightGray" TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="LightGray" />
</Style>
</Window.Resources>
<!-- View -->
<Grid x:Name="gridVorh">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical">
<DataGrid x:Name="dgVorh" ItemsSource="{Binding CollTop}" SelectedItem="{Binding SelItem}"
Margin="5" Grid.Row="0"
SelectionMode="Single" SelectionUnit="FullRow" IsReadOnly="False"
CanUserAddRows="False" CanUserDeleteRows="False" AutoGenerateColumns="False"
BorderBrush="Black" BorderThickness="2" RowHeight="30" FontFamily="Arial Narrow" FontSize="18">
<!-- Style Column Headers -->
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Foreground" Value="#FFFFFF"/>
<Setter Property="Background" Value="#DD002C"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="BorderThickness" Value="0,0,1,2"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Height" Value="30"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Angelegt am" Binding="{Binding Angelegt_am}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextBlock.Background" Value="LightGray"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Bearbeiter" Binding="{Binding Bearbeiter}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Bestelldatum" Binding="{Binding Bestelldatum}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Bestellt bei" Binding="{Binding Empfaenger}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Lieferung zu" Binding="{Binding Anlieferungsort}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Liefername" Binding="{Binding Adressat}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Lieferanschrift" Binding="{Binding Anschrift}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Lieferort" Binding="{Binding Plz_Ort}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Liefertermin" Binding="{Binding Liefertermin}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
</DataGrid.Columns>
</DataGrid>
<!-- ARTIKEL ZUR NACHBESTELLUNG -->
<DataGrid x:Name="dgVorhArtikel" ItemsSource="{Binding SelItem.artikelliste}"
Margin="5" Grid.Row="0"
SelectionMode="Single" SelectionUnit="Cell" IsReadOnly="False"
CanUserAddRows="False" CanUserDeleteRows="False" AutoGenerateColumns="False"
BorderBrush="Black" BorderThickness="2" RowHeight="30" FontFamily="Arial Narrow" FontSize="18">
<!-- Style Column Headers -->
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Foreground" Value="#FFFFFF"/>
<Setter Property="Background" Value="#DD002C"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="BorderThickness" Value="0,0,1,2"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Height" Value="30"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Pos" Binding="{Binding Pos}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Artikelbezeichnung" Binding="{Binding Artikelbezeichnung}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Artikelnummer" Binding="{Binding Artikelnummer}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Einheit" Binding="{Binding Einheit}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Menge" Binding="{Binding Menge}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Einzelpreis" Binding="{Binding Einzelpreis}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Gesamtpreis" Binding="{Binding Gesamtpreis}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Anforderungsgrund" Binding="{Binding Anforderungsgrund}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Anforderungsnr" Binding="{Binding Anforderungsnr}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Anforderer" Binding="{Binding Anforderer}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Rechnungsnr" Binding="{Binding Rechnungsnr}"/>
<DataGridTextColumn Header="AB-Nr" Binding="{Binding ABnr}"/>
<DataGridTextColumn Header="ÄndDatum" Binding="{Binding LetzteAktualisierung}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Bemerkungen" Binding="{Binding Bemerkungen}"/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
<StackPanel Name="stpnlUpdate" Grid.Row="1" HorizontalAlignment="Center">
<Button Name="btnUpdate" Content="Aktualisieren"
Background="#DD002C" Foreground="White"
BorderThickness="2" BorderBrush="Black"
Click="BtnUpdate_Click"
Height="40" Width="130"
FontFamily="Verdana" FontStyle="Oblique"
FontStretch="ExtraCondensed" FontSize="15"
FontWeight="ExtraBlack"
MouseEnter="BtnUpdate_MouseEnter" MouseLeave="BtnUpdate_MouseLeave">
</Button>
</StackPanel>
</Grid>
CODE BEHIND
public partial class vorhandeneNachbestellungen : Window
{
public vorhandeneNachbestellungen(string hv)
{
InitializeComponent();
this.DataContext = new vorhandeneNachbestellungenViewModel(hv);
}
VIEW MODEL
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace Nachbestellungen
{
public class vorhandeneNachbestellungenViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private ObservableCollection<Nachbestellung> _collTop;
public ObservableCollection<Nachbestellung> CollTop
{
get { return _collTop; }
set
{
_collTop = value;
OnPropertyChanged("CollTop");
}
}
private ObservableCollection<Artikel> _collBot;
public ObservableCollection<Artikel> CollBot
{
get { return _collBot; }
set
{
_collBot = value;
OnPropertyChanged("CollBot");
}
}
private Nachbestellung _selItem;
public Nachbestellung SelItem
{
get { return _selItem; }
set
{
_selItem = value;
OnPropertyChanged("SelItem");
}
}
public vorhandeneNachbestellungenViewModel(string hv)
{
try
{
//connecting to database
var crud = new MongoCRUD("avdb");
//get filtered records (filtered by Id which is "Hv": hv)
var erg = crud.LoadRecords<Nachbestellung>("nachbestellungen", hv);
//filtered List is an ObservableCollection which is updated with OnPropertyChanged method
CollTop = new ObservableCollection<Nachbestellung>(erg);
//same procedure for the articles collection....
//var arterg = crud.LoadRecords<Artikel>("bestellteArtikel", hv);
CollBot = new ObservableCollection<Artikel>();
for (int i = 0; i < CollTop.Count; i++)
{
foreach (var a in CollTop[i].artikelliste)
{
CollBot.Add(a);
}
}
//wenn Abfrageergebnis null ist, dann Messagebox-Info (Zu dieser Hv wurde keine Nachbestellung gefunden!)
if (CollBot.Count <= 0)
{
MessageBox.Show("Zu dieser Hv wurde keine Nachbestellung gefunden!",
"Keine Daten vorhanden!", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
catch(Exception e)
{
MessageBox.Show(e.Message);
}
}
}
}
回答1:
The SelItem property inside my view model is the key to success here because it does all the join work for you. You need to bind it to the TOP DATAGRID and then for the BOTTOM DATAGRID you just bind the ITEM SOURCE to SelValue.PropertyListOfYourModel (in my case the artikelliste[] inside REORDER=Nachbestellung) .... In this way you don't even need the collection CollBot anymore!!!...because through the magic of databinding your MongoDB already knows which parts belong together! I hope this helps other developers as well in the future:
XAML
<Window x:Class="Nachbestellungen.vorhandeneNachbestellungen"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Nachbestellungen"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Title="Vorhandene Nachbestellungen" WindowState="Maximized" WindowStyle="ThreeDBorderWindow">
<Window.Resources>
<Style x:Key="cellLightGray" TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="LightGray" />
</Style>
</Window.Resources>
<!-- View -->
<Grid x:Name="gridVorh">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical">
<DataGrid x:Name="dgVorh" ItemsSource="{Binding CollTop}" SelectedItem="{Binding SelItem}"
Margin="5" Grid.Row="0"
SelectionMode="Single" SelectionUnit="FullRow" IsReadOnly="False"
CanUserAddRows="False" CanUserDeleteRows="False" AutoGenerateColumns="False"
BorderBrush="Black" BorderThickness="2" RowHeight="30" FontFamily="Arial Narrow" FontSize="18">
<!-- Style Column Headers -->
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Foreground" Value="#FFFFFF"/>
<Setter Property="Background" Value="#DD002C"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="BorderThickness" Value="0,0,1,2"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Height" Value="30"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Angelegt am" Binding="{Binding Angelegt_am}" IsReadOnly="True">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextBlock.Background" Value="LightGray"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Bearbeiter" Binding="{Binding Bearbeiter}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Bestelldatum" Binding="{Binding Bestelldatum}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Bestellt bei" Binding="{Binding Empfaenger}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Lieferung zu" Binding="{Binding Anlieferungsort}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Liefername" Binding="{Binding Adressat}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Lieferanschrift" Binding="{Binding Anschrift}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Lieferort" Binding="{Binding Plz_Ort}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Liefertermin" Binding="{Binding Liefertermin}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
</DataGrid.Columns>
</DataGrid>
<!-- ARTIKEL ZUR NACHBESTELLUNG -->
<DataGrid x:Name="dgVorhArtikel" ItemsSource="{Binding SelItem.artikelliste}"
Margin="5" Grid.Row="0"
SelectionMode="Single" SelectionUnit="Cell" IsReadOnly="False"
CanUserAddRows="False" CanUserDeleteRows="False" AutoGenerateColumns="False"
BorderBrush="Black" BorderThickness="2" RowHeight="30" FontFamily="Arial Narrow" FontSize="18">
<!-- Style Column Headers -->
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Foreground" Value="#FFFFFF"/>
<Setter Property="Background" Value="#DD002C"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="BorderThickness" Value="0,0,1,2"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Height" Value="30"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Header="Pos" Binding="{Binding Pos}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Artikelbezeichnung" Binding="{Binding Artikelbezeichnung}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Artikelnummer" Binding="{Binding Artikelnummer}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Einheit" Binding="{Binding Einheit}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Menge" Binding="{Binding Menge}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Einzelpreis" Binding="{Binding Einzelpreis}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Gesamtpreis" Binding="{Binding Gesamtpreis}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Anforderungsgrund" Binding="{Binding Anforderungsgrund}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Anforderungsnr" Binding="{Binding Anforderungsnr}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Anforderer" Binding="{Binding Anforderer}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Rechnungsnr" Binding="{Binding Rechnungsnr}"/>
<DataGridTextColumn Header="AB-Nr" Binding="{Binding ABnr}"/>
<DataGridTextColumn Header="ÄndDatum" Binding="{Binding LetzteAktualisierung}" IsReadOnly="True" ElementStyle="{StaticResource cellLightGray}"/>
<DataGridTextColumn Header="Bemerkungen" Binding="{Binding Bemerkungen}"/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
<StackPanel Name="stpnlUpdate" Grid.Row="1" HorizontalAlignment="Center">
<Button Name="btnUpdate" Content="Aktualisieren"
Background="#DD002C" Foreground="White"
BorderThickness="2" BorderBrush="Black"
Click="BtnUpdate_Click"
Height="40" Width="130"
FontFamily="Verdana" FontStyle="Oblique"
FontStretch="ExtraCondensed" FontSize="15"
FontWeight="ExtraBlack"
MouseEnter="BtnUpdate_MouseEnter" MouseLeave="BtnUpdate_MouseLeave">
</Button>
</StackPanel>
</Grid>
CODE BEHIND
public partial class vorhandeneNachbestellungen : Window
{
public vorhandeneNachbestellungen(string hv)
{
InitializeComponent();
this.DataContext = new vorhandeneNachbestellungenViewModel(hv);
}
VIEW MODEL
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
namespace Nachbestellungen
{
public class vorhandeneNachbestellungenViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private ObservableCollection<Nachbestellung> _collTop;
public ObservableCollection<Nachbestellung> CollTop
{
get { return _collTop; }
set
{
_collTop = value;
OnPropertyChanged("CollTop");
}
}
private ObservableCollection<Artikel> _collBot;
public ObservableCollection<Artikel> CollBot
{
get { return _collBot; }
set
{
_collBot = value;
OnPropertyChanged("CollBot");
}
}
private Nachbestellung _selItem;
public Nachbestellung SelItem
{
get { return _selItem; }
set
{
_selItem = value;
OnPropertyChanged("SelItem");
}
}
public vorhandeneNachbestellungenViewModel(string hv)
{
try
{
//connecting to database
var crud = new MongoCRUD("avdb");
//get filtered records (filtered by Id which is "Hv": hv)
var erg = crud.LoadRecords<Nachbestellung>("nachbestellungen", hv);
//filtered List is an ObservableCollection which is updated with OnPropertyChanged method
CollTop = new ObservableCollection<Nachbestellung>(erg);
//same procedure for the articles collection....
//var arterg = crud.LoadRecords<Artikel>("bestellteArtikel", hv);
CollBot = new ObservableCollection<Artikel>();
for (int i = 0; i < CollTop.Count; i++)
{
foreach (var a in CollTop[i].artikelliste)
{
CollBot.Add(a);
}
}
//wenn Abfrageergebnis null ist, dann Messagebox-Info (Zu dieser Hv wurde keine Nachbestellung gefunden!)
if (CollBot.Count <= 0)
{
MessageBox.Show("Zu dieser Hv wurde keine Nachbestellung gefunden!",
"Keine Daten vorhanden!", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
catch(Exception e)
{
MessageBox.Show(e.Message);
}
}
}
}
来源:https://stackoverflow.com/questions/58799113/how-to-query-2-collections-into-2-datagrids-with-mongodb-driver-and-binding