2017-01-10 3 views
0

Im работает над небольшим проектом wpf, чтобы лучше понять C# и mvvm. У меня в настоящее время проблема, что я не знаю, как передавать данные между двумя страницами. Что я хочу делать: У меня две страницы, это содержание моего MainWindow. В PageViewCustomers у меня есть DatagridView (есть два, но мне нужно только одно для этой задачи), когда я дважды щелкаю по строке, я открываю PageAddStaticIPAddress. Теперь я хочу иметь доступ к строке, которую я дважды щелкнул в PageViewCustomers в PageAddStaticIPAddress. Я думал о передаче выделенной строки в качестве параметра CommandParameter в xaml pageViewCustomers. Но теперь я не знаю, как получить к нему доступ из PageAddStaticIPAddress .. Я видел некоторые решения, но все они решают это, имея код в представлении. Я стараюсь как можно меньше использовать код в представлении и решает его, используя только Bindings, команды и мои режимы просмотра.C# Передача данных между двумя страницами WPF MVVM

Вот мой текущий код:

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> 

Класс VModel.cs (VModel из 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 
} 

Page 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 
} 

Я надеюсь, вы понимаете мою проблему ;-) Если у вас есть какие-либо вопросы, дайте мне знать. Спасибо!

EDIT: Как открыть AddIPAddress я связать команду с DataGrid, где у меня есть командный OpenAddNewIPAddress:

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

Команда выглядит следующим образом:

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

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

Это другое вопрос у меня был. Когда я устанавливаю содержимое моего MainWindow (System.Windows.Application.Current.MainWindow.Content = new AddStaticIPAddress();) с новой страницей, строка меню теряется ... Есть ли лучший способ сделать это?

+0

Как вы «открываете» PageAddStaticIPAddress? – mm8

+0

Я отредактировал мое сообщение :) –

ответ

1

Вы можете вводить AddIPAddressVModel с параметром командной строки.Что-то вроде этого:

<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 
} 

Удалить это с точки зрения AddStaticIPAddress:

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

Страница должна наследовать DataContext. Установка DataContext в разметке XAML полезна только в очень простых сценариях, когда модель представления не имеет зависимостей.

+0

Спасибо, это похоже на то, что я хочу сделать ;-) Я реализовал ваше решение, но Я получаю сообщение об ошибке, как только открываю ошибку Обзор: System.Windows.Data: 40: Ошибка пути BindingExpression: свойство «SelectedItem» не найдено на «объекте» «VModel» (HashCode = 30369281) ». BindingExpression: Path = SelectedItem; DataItem = 'VModel' (HashCode = 30369281); целевым элементом является «MouseBinding» (HashCode = 18183789); target свойство «CommandParameter» (тип «Object») –

+0

Как наследовать DataContext? Я всегда делал это так:/ –

+1

Это унаследовано автоматически при условии, что вы явно не задали DataContext страницы. В примере кода, который я разместил, я установил DataContext окна в экземпляр AddIPAddressVModel, а Content (AddStaticIPAddress) затем наследует это. – mm8

0

Попробуйте поставить поле в AddStaticIPAddress:

public DataGridRow Row { get; set; } 

Таким образом, вы можете получить доступ к нему из VModel. . вы можете инициализировать AddIPAddressVModel на DataGridSelectionChanged действия:

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

Спасибо за ваш ответ! Вы имеете в виду DataGrid вместо dgCustomer? Поскольку класс DgCustomer не существует. В моем xaml я просто ссылаюсь на Datagrid на dgCustomer. Итак, iput поле dgCustomer в AddStaticIPaddressVModel? До сих пор я просто использую его в VModel. А затем в VModel я пишу _OnSelectionChanged (я передаю параметры здесь?), Так что я смогу получить доступ к выбранному элементу в моем AddAdAdAdessVModel? –

+0

Да, если вы хотите отправить 'DataGridRow', но я не уверен, что вы можете легко получить доступ к' DataGridRow' из вашего 'DataGrid' – msmych

Смежные вопросы