【问题标题】:How to send gridview selected row data to another window with textboxes in wpf using mvvm如何使用 mvvm 在 wpf 中使用文本框将 gridview 选定的行数据发送到另一个窗口
【发布时间】:2024-04-23 09:55:02
【问题描述】:

我在谷歌上尝试了很多解决这个问题的方法,但似乎都没有帮助。 我在每一行都有一个按钮,单击该按钮会打开一个带有文本框的新窗口。此窗口应显示选定的行单元格数据。 我从 mysql 数据库加载数据网格。

查看

第二个窗口的文本框 (XML)

<Label Content="{Binding sFirstName, Mode=OneWay }" /><Label Content="{Binding sLastName, Mode=OneWay }" />

数据网格

<DataGrid ItemsSource="{Binding Path=MM}" SelectionMode="Extended" SelectedItem="{Binding SelectedItem}" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=sFirstName}" />
<DataGridTextColumn Binding="{Binding Path=sLastName}" />
</DataGrid.Columns>

型号

public class MM : INotifyPropertyChanged
   {
       public event PropertyChangedEventHandler PropertyChanged;
       public void OnPropertyChanged([CallerMemberName]string PropertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName)); }

       private string _sFirstName, _sLastName;

       public string sFirstName { get { return _sFirstName; } set { if (_sFirstName != value) { _sFirstName = value; OnPropertyChanged("sFirstName"); } } }

       public string sLastName { get { return _sLastName; } set { if (_sLastName != value) { _sLastName = value; OnPropertyChanged("sLastName"); } } }

       public DataRowView SelectedRow
       {
           get { return SelectedRow; }
           set { SelectedRow = value; OnPropertyChanged("SelectedItem"); }
       }
}

查看模型

Public class MV : INotifyPropertyChanged
{
private ICommand cmdLoad;
public ICommand CmdLoad { get { if (cmdLoad == null) cmdLoad = new RelayCommand(p => OnLoad()); return cmdLoad; } }

private void OnLoad() { Load(); }

public ObservableCollection<FinTuitionM> finTuitionM { get; set; }
       
public ClrIdVMD()
{
Load();
}

public void Load()
{

}
}

代码隐藏 (cs)

public partial class Home : Window
{
MV mv;
public Home()
{ InitializeComponent();
mv = new MV(); DataContext = mv;
}
}

【问题讨论】:

  • 你设置了DataContext = new MV();。然后你设置一个绑定到它&lt;DataGrid ItemsSource="{Binding Path=MM}" ... SelectedItem="{Binding SelectedItem}" &gt;。但是类型 MV 没有属性 MM и SelectedItem。从侧面看,一般来说,你在做什么是没有意义的。请提供进一步的说明。
  • 您不需要创建一个会占用大量内存的新 MV()。您可以在构造函数中传递内容:public Home(DataContext mv),然后在调用 Home 类时添加参数:new Home(context);

标签: c# mysql xml wpf mvvm


【解决方案1】:

你似乎很困惑,所以我准备了一个小例子来说明我认为你正在努力实现的目标。

我猜您想要一个基本上只读的主视图,并且您打算使用弹出窗口进行更改。在此基础上,主窗口的 View Model 不需要实现 INotifyPropertyChanged。所以一个简单的视图模型应该是这样的:

public class MV 
{

    public ObservableCollection<MM> MMs { get; set; }

    private ICommand cmdShowDetails;
    public ICommand CmdShowDetails
    {
        get
        {
            if (cmdShowDetails == null) cmdShowDetails = new RelayCommand(p => ShowDetails());
            return cmdShowDetails;
        }
    }

    public void ShowDetails()
    {
        var detVM = new DetailsVM(SelectedItem);
        var dets = new DetailsWindow(detVM);
        dets.ShowDialog();
    }

    public MV()
    {
        MMs = new ObservableCollection<MM>
        {
            new MM{sFirstName = "Mickey", sLastName = "Mouse"},
            new MM{sFirstName = "Donald", sLastName = "Duck"},
            new MM{sFirstName = "Roger", sLastName = "Rabbit"},
        };
    }
    public MM SelectedItem { get; set; }

}

请注意,出于演示目的,我在ObservableCollection 中加载了一些虚拟数据。在您的情况下,这将替换为数据库中的数据。

this 引用的 MM 类看起来像这样:

public class MM : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChangedEvent(string propertyName)
    {
        if (PropertyChanged != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            PropertyChanged(this, e);
        }
    }

    private string firstName;
    public string sFirstName
    {
        get { return firstName; }
        set
        {
            if (firstName == value)
            {
                return;
            }
            firstName = value;
            RaisePropertyChangedEvent("sFirstName");
        }
    }
    private string lastName;
    public string sLastName
    {
        get { return lastName; }
        set
        {
            if (lastName == value)
            {
                return;
            }
            lastName = value;
            RaisePropertyChangedEvent("sLastName");
        }
    }
}

注意SelectedItem在View Model(MV)中,是MM类的一个对象,这样当第二个窗口打开时,ShowDetails命令可以传递选中的细节。

因此,这需要一个新的非常简单的视图模型用于第二个(详细信息)窗口:

public class DetailsVM
{
    public MM Detail { get; set; }

    public DetailsVM(MM detail)
    {
        Detail = detail;
    }
}

主窗口网格 xaml 现在如下所示:

<Grid>
    <DockPanel>
        <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
            <Button Content="Show Details" Command="{Binding CmdShowDetails}"></Button>
        </StackPanel>            
        <DataGrid ItemsSource="{Binding MMs}" SelectedItem="{Binding SelectedItem}"  AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name" Binding="{Binding sFirstName}" />
                <DataGridTextColumn Header="Last Name" Binding="{Binding sLastName}" />
            </DataGrid.Columns>
        </DataGrid>
    </DockPanel>
</Grid>

请注意,我在窗口底部只有一个按钮来传输详细信息。这是因为详细信息来自所选项目,即突出显示的行。

后面的代码很简单:

public partial class MainWindow : Window
{
    private MV _mV;
    public MainWindow()
    {

        InitializeComponent();
        _mV = new MV();
        DataContext = _mV;
    }
}

最后是第二个(详细信息)窗口的 xaml

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="40*"/>
        <RowDefinition Height="40*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="70*"/>
        <ColumnDefinition Width="200*"/>
    </Grid.ColumnDefinitions>
    <Label Content="First Name" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center"/>
    <TextBox Text="{Binding Detail.sFirstName}" Grid.Column="1" Grid.Row="0" Width="150" Height="25" HorizontalAlignment="Left" />
    <Label Content="Last Name" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center"/>
    <TextBox Text="{Binding Detail.sLastName}" Grid.Column="1" Grid.Row="1" Width="150" Height="25" HorizontalAlignment="Left" />
</Grid>

注意这里绑定的是 Detail.sFirstName 和 Detail.sLastName。 DataContext 是一个 DetailsVM 对象,它具有 MM 类型的属性 Detail,因此 sFirstName 和 sLastName 是 Detail 的子属性。

这个窗口后面还有一段很简单的代码:

public partial class DetailsWindow : Window
{
    private DetailsVM _details;
    public DetailsWindow(DetailsVM details)
    {
        _details = details;
        DataContext = _details;
        InitializeComponent();
    }
}

如果您现在运行此程序,您会发现在第二个窗口中所做的更改会自动反映回主窗口。在实践中,您可能需要在第二个窗口中显示“保存”和“取消”按钮。

我希望以上内容足以为您指明正确的方向!

【讨论】:

    最近更新 更多