簡體   English   中英

C#在兩個頁面WPF MVVM之間傳遞數據

[英]C# Pass data between two Pages WPF MVVM

我正在研究一個小的wpf項目,以更好地理解c#和mvvm。 我目前遇到問題,我不知道如何在兩個頁面之間傳遞數據。 我想做什么:我有兩個頁面,它們是MainWindow的內容。 在PageViewCustomers中,我有一個DatagridView(實際上有兩個,但是我只需要一個),當我雙擊一行時,我打開PageAddStaticIPAddress。 現在,我希望能夠訪問在PageAddStaticIPAddress的PageViewCustomers中雙擊的行。 我考慮過將所選行作為CommandParameter傳遞給PageViewCustomers的xaml。 但是現在我不知道如何從PageAddStaticIPAddress訪問它。我已經看到了一些解決方案,但是他們都通過在View中添加代碼來解決它。 我嘗試在視圖中盡可能減少代碼,僅通過使用Bindings,命令和我的viewmodels來解決它。

這是我當前的代碼:

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類(PageViewCustomers的VModel)

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
}

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

希望您理解我的問題;-)如果您有任何疑問,請告訴我。 謝謝!

編輯:我如何打開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); } }

我有另一個問題。 當我用新的Page設置MainWindow的內容(System.Windows.Application.Current.MainWindow.Content = new AddStaticIPAddress();)時,菜單欄會丟失...有更好的方法嗎?

您可以使用命令參數注入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>

Page應該繼承其DataContext。 在XAML標記中設置DataContext僅在視圖模型沒有依賴項的非常簡單的情況下有用。

嘗試在AddStaticIPAddress放置一個字段:

public DataGridRow Row { get; set; }

因此,您可以從VModel訪問它。 例如,您可以在DataGridSelectionChanged操作上初始化AddIPAddressVModel

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM