2017-01-10 6 views
0

Ich arbeite an einem kleinen WPF-Projekt zu verstehen, C# und MVVM besser. Im Moment habe ich ein Problem, dass ich nicht weiß, wie Daten zwischen zwei Seiten übergeben werden. Was ich machen möchte: Ich habe zwei Seiten, sie sind der Inhalt meines MainWindow. In PageViewCustomers habe ich eine DatagridView (es gibt tatsächlich zwei, aber ich brauche nur eine für diese Aufgabe), wenn ich auf eine Zeile doppelklicke, öffne ich PageAddStaticIPAddress. Nun möchte ich auf die Zeile zugreifen können, auf die ich in PageViewCustomers in der PageAddStaticIPAddress geklickt habe. Ich dachte darüber nach, die ausgewählte Zeile als CommandParameter in der xaml von PageViewCustomers zu übergeben. Aber jetzt weiß ich nicht, wie man es von PageAddStaticIPAddress erreicht. Ich habe einige Lösungen gesehen, aber sie alle lösen es, indem sie Code in der Ansicht haben. Ich versuche, so wenig Code in der Ansicht wie möglich zu haben und es zu lösen, indem ich nur Bindings, Befehle und meine viewmodels verwende.C# Pass Daten zwischen zwei Seiten WPF MVVM

Hier ist meine aktuellen Code:

PageViewCustomers.xaml

<Page x:Class="StaticIPConfiger.PageViewCustomers" 
    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:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:local="clr-namespace:StaticIPConfiger" 
    xmlns:localvm="clr-namespace:StaticIPConfiger.Modelle" 
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="500" 
    Title="Kundenübersicht"> 
<Page.DataContext> 
    <localvm:VModel /> 
</Page.DataContext> 

<Grid DataContext="{Binding}" > 
    <DataGrid IsReadOnly="True" Name="dgCustomers" ItemsSource="{Binding AlleKunden}" AutoGenerateColumns="False" Margin="0,0,0,197"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Header="Name" Binding="{Binding Path=c_name}" Width="*"></DataGridTextColumn> 
      <DataGridTextColumn Header="Standort" Binding="{Binding Path=l_name}" Width="*"></DataGridTextColumn> 
     </DataGrid.Columns> 
     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="SelectionChanged"> 
       <i:InvokeCommandAction Command="{Binding UpdateLocations}" 
       CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=SelectedItem}" /> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
    </DataGrid> 
    <DataGrid IsReadOnly="True" Name="dg2Customers" ItemsSource="{Binding AlleStandorte}" AutoGenerateColumns="False" Margin="0,168,0,10" > 
     <DataGrid.InputBindings> 
      <MouseBinding Gesture="LeftDoubleClick" Command="{Binding OpenAddNewIPAddress}" 
          CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=SelectedItem}"/> 
     </DataGrid.InputBindings> 
     <DataGrid.Columns> 
      <DataGridTextColumn Header="StandortId" Binding="{Binding Path=l_id}" Width="*"></DataGridTextColumn> 
      <DataGridTextColumn Header="Standort" Binding="{Binding Path=l_name}" Width="*"></DataGridTextColumn> 
     </DataGrid.Columns> 
    </DataGrid> 
</Grid> 

Klasse VModel.cs (VModel von PageViewCustomers)

namespace StaticIPConfiger.Modelle { 

public class VModel : INotifyPropertyChanged { 
    DataView _alleKunden; 
    public VModel() { 
     DataTable dt = new DataTable(); 
     using (SqlConnection connection = new SqlConnection("Data Source=.\\WERBASWEB;Initial Catalog=customer;Persist Security Info=True;User ID=sa;Password=Dotnet123!")) { 
      SqlDataAdapter adapter = new SqlDataAdapter(); 
      adapter.SelectCommand = new SqlCommand("Select c_id,c_name, l_id,l_name, a_town, a_pcode, a_street from dbo.[AllCustomers]", connection); 
      adapter.Fill(dt); 
     } 
     AlleKunden = dt.DefaultView; 
     AlleStandorte = null; 

    } 

    public DataView AlleKunden { get; private set; } 

    public DataView AlleStandorte { get { return _alleKunden; } private set { _alleKunden = value; 
      RaisePropertyChanged("AlleStandorte"); 
     } } 

    #region INotifyPropertyChanged Members 
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion 

    #region Methods 

    private void RaisePropertyChanged(string propertyName) { 
     // take a copy to prevent thread issues 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    #endregion 

    #region Commands 
    void UpdateLocationView(object parameter) { 
     DataRowView selectedRow = (DataRowView)parameter; 
     string customerid = selectedRow.Row[0].ToString(); 
     string locationid = selectedRow.Row[2].ToString(); 
     DataTable dt = SelectStatements.SelectLocationsForCustomer(locationid,customerid); 
     AlleStandorte = dt.DefaultView; 
     Console.WriteLine("Test"); 
    } 

    bool CanUpdateLocationView(object parameter) { 
     return true; 
    } 

    public ICommand UpdateLocations { get { return new RelayCommand<object>(param => this.UpdateLocationView(param), param => this.CanUpdateLocationView(param)); } } 

    void OpenIPAddress() { 
     System.Windows.Application.Current.MainWindow.Content = new AddStaticIPAddress(); 
    } 

    bool CanOpenIPAddress() { 
     return true; 
    } 
    public ICommand OpenAddNewIPAddress { get { return new RelayCommand(OpenIPAddress,CanOpenIPAddress); } } 
    #endregion 
} 

Seite AddStaticIPAddress:

<Page x:Class="StaticIPConfiger.AddStaticIPAddress" 
    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:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:local="clr-namespace:StaticIPConfiger" 
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="500" 
    Title="AddStaticIPAddress"> 

<Page.DataContext> 
    <local:AddCustomerVModel/> 
</Page.DataContext> 
<Grid> 
    <Label x:Name="lbl_net" Content="Netz:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/> 
    <Label x:Name="lbl_subnetmask" Content="Subetnmaske:" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,36,0,0"/> 
    <Label x:Name="label_ipaddress" Content="IP Addresse:" HorizontalAlignment="Left" Margin="10,62,0,0" VerticalAlignment="Top"/> 
    <TextBox x:Name="text_net" Text="" HorizontalAlignment="Left" Height="23" Margin="103,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/> 
    <TextBox x:Name="text_subetnmask" Text="" HorizontalAlignment="Left" Height="23" Margin="103,36,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/> 
    <TextBox x:Name="text_ipaddress" Text="" HorizontalAlignment="Left" Height="23" Margin="103,62,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/> 
    <Label x:Name="lbl_description" Content="Bezeichnung:" HorizontalAlignment="Left" Margin="10,85,0,0" VerticalAlignment="Top"/> 
    <TextBox x:Name="text_description" Text="" HorizontalAlignment="Left" Height="23" Margin="103,88,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/> 
    <Button x:Name="btn_save_add_ip" Content="IP Addresse hinzufügen" Command ="" HorizontalAlignment="Left" Margin="10,129,0,0" VerticalAlignment="Top" Width="133"/> 
    <Button x:Name="btn_abort_add_ip" Content="Verwerfen" HorizontalAlignment="Left" Margin="148,129,0,0" VerticalAlignment="Top" Width="75"/>  
</Grid> 

AddIPAddressVModel:

namespace StaticIPConfiger.Modelle { 
    class AddIPAddressVModel : INotifyPropertyChanged { 
    IPAddress _ipaddress; 

    public AddIPAddressVModel() { 
     _ipaddress = new IPAddress { Net = "", Subetnmask = "", IpAddress = ""}; 
    } 


    public IPAddress IPAddress { 
     get { return _ipaddress; } 
     set { _ipaddress = value; } 
    } 
    #region"Get/Set" 
    public int Id { 
     get { return IPAddress.Id; } 
     set { 
      IPAddress.Id = value; 
      RaisePropertyChanged("IPAddress"); 
     } 
    } 

    public String Net { 
     get { return IPAddress.Net; } 
     set { 
      IPAddress.Net= value; 
      RaisePropertyChanged("Net"); 
     } 
    } 

    public string Subnetmask { 
     get { return IPAddress.Subetnmask; } 
     set { 
      IPAddress.Subetnmask = value; 
      RaisePropertyChanged("Subetnmask"); 
     } 
    } 

    public string IpAddress { 
     get { return IPAddress.IpAddress; } 
     set { 
      IPAddress.IpAddress = value; 
      RaisePropertyChanged("IPAddress"); 
     } 
    } 
    #endregion 

    #region INotifyPropertyChanged Members 
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion 

    #region Methods 

    private void RaisePropertyChanged(string propertyName) { 
     // take a copy to prevent thread issues 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    #endregion 
} 

Ich hoffe, dass Sie mein Problem verstehen ;-) Wenn Sie Fragen haben, lassen Sie es mich wissen. Danke!

EDIT: Wie ich AddIPAddress öffnen ich einen Befehl an das Datagrid gebunden haben, wo ich einen Befehl OpenAddNewIPAddress haben:

<DataGrid.InputBindings> 
     <MouseBinding Gesture="LeftDoubleClick" Command="{Binding OpenAddNewIPAddress}" 
         CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=SelectedItem}"/> 
</DataGrid.InputBindings> 

Der Befehl sieht wie folgt aus:

void OpenIPAddress() { 
    System.Windows.Application.Current.MainWindow.Content = new AddStaticIPAddress(); 
} 

bool CanOpenIPAddress() { 
    return true; 
} 
public ICommand OpenAddNewIPAddress { get { return new RelayCommand(OpenIPAddress,CanOpenIPAddress); } } 

, dass ein anderer Frage hatte ich. Wenn ich den Inhalt meines MainWindow (System.Windows.Application.Current.MainWindow.Content = new AddStaticIPAddress();) mit einer neuen Seite einstelle, geht die Menüleiste verloren ... Gibt es dafür einen besseren Weg?

+0

Wie öffne ich "PageAddStaticIPAddress"? – mm8

+0

Ich habe meinen Beitrag bearbeitet :) –

Antwort

1

Sie konnten die AddIPAddressVModel mit dem Befehlsparameter injizieren.Etwas wie folgt aus:

<DataGrid IsReadOnly="True" Name="dg2Customers" ItemsSource="{Binding AlleStandorte}" AutoGenerateColumns="False" Margin="0,168,0,10" > 
    <DataGrid.InputBindings> 
     <MouseBinding Gesture="LeftDoubleClick" Command="{Binding OpenAddNewIPAddress}"CommandParameter="{Binding SelectedItem}"/> 
    </DataGrid.InputBindings> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="StandortId" Binding="{Binding Path=l_id}" Width="*"></DataGridTextColumn> 
     <DataGridTextColumn Header="Standort" Binding="{Binding Path=l_name}" Width="*"></DataGridTextColumn> 
    </DataGrid.Columns> 
</DataGrid> 

void OpenIPAddress(object parameter) 
{ 
    System.Windows.Application.Current.MainWindow.DataContext = new AddIPAddressVModel(parameter as DataRowView) 
    System.Windows.Application.Current.MainWindow.Content = new AddStaticIPAddress(); 
} 

bool CanOpenIPAddress(object parameter) 
{ 
    return true; 
} 

public ICommand OpenAddNewIPAddress { get { return new RelayCommand<object>(OpenIPAddress, CanOpenIPAddress); } } 

public AddIPAddressVModel(DataRowView drv) { 
    _ipaddress = new IPAddress { Net = "", Subetnmask = "", IpAddress = ""}; 
    _drv = drv; //keep a reference to the clicked DataRowView 
} 

entfernen diese aus der AddStaticIPAddress Ansicht:

<Page.DataContext> 
    <local:AddCustomerVModel/> 
</Page.DataContext> 

Die Seite sollte seine Datacontext erben. Das Festlegen des DataContext im XAML-Markup ist nur in sehr einfachen Szenarien sinnvoll, wenn das View-Modell keine Abhängigkeiten aufweist.

+0

Danke, das sieht aus wie ich es machen möchte ;-) Ich habe Ihre Lösung aber implementiert Ich erhalte eine Fehlermeldung, sobald ich den Overview: System.Windows.Data Error: 40: BindingExpression Pfadfehler: 'SelectedItem' Eigenschaft nicht auf 'Objekt' '' 'VModel' (HashCode = 30369281) 'gefunden. BindingExpression: Pfad = SelectedItem; DataItem = 'VModel' (HashCode = 30369281); Zielelement ist 'MouseBinding' (HashCode = 18183789); Zieleigenschaft ist 'CommandParameter' (Typ 'Objekt') –

+0

Wie erben ich den DataContext? Ich habe es immer so gemacht:/ –

+1

Es wird automatisch geerbt, vorausgesetzt, dass Sie den DataContext der Seite nicht explizit festlegen. In dem Beispielcode, den ich gepostet habe, setze ich den DataContext des Fensters auf eine Instanz des AddIPAddressVModel und der Inhalt (AddStaticIPAddress) erbt dies dann. – mm8

0

Versuchen Sie, ein Feld in AddStaticIPAddress zu setzen:

public DataGridRow Row { get; set; } 

So können Sie es von VModel zugreifen. Zum Beispiel Sie können AddIPAddressVModel auf DataGridSelectionChanged Aktion initialisieren:

private void dgCustomers_OnSelectionChanged(...) 
{ 
    AddIPAddressVModel addip = new AddIPAddressVModel(); 
    addip.Row = (DataGridRow) dgCustomers.SelectedItem; 
    addip.Show(); 
} 
+0

Danke für deine Antwort! Meinst du DataGrid statt dgCustomer? Weil die Klasse DgCustomer nicht existiert. In meinem XAML referenziere ich nur das Datagrid von dgCustomer. Also iput das Feld dgCustomer in AddStaticIPaddressVModel? Bis jetzt benutze ich es nur in VModel. Und dann schreibe ich in VModel _OnSelectionChanged (gebe ich Parameter hier?), So dass ich auf das selectedItem in meinem AddIPAddessVModel zugreifen kann? –

+0

Ja, wenn Sie 'DataGridRow' senden wollen, aber ich bin mir nicht sicher, ob Sie einfach' DataGridRow' von Ihrem 'DataGrid' erreichen können – msmych