如何使用mvvm在wpf中将gridview选中的行数据发送到另一个带有文本框的窗口



我在谷歌上尝试了很多关于这个问题的解决方案,但似乎都没有帮助。我在每一行都有一个按钮,点击后会打开一个带有文本框的新窗口。此窗口应显示选定的行单元格数据。我从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;
}
}

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

我猜你想要一个基本上只读的主视图,并且你打算使用弹出窗口来进行更改。在此基础上,主窗口的视图模型不需要实现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。在您的情况下,这将被数据库中的数据所取代。

这所指的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位于视图模型(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对象,其属性Detail类型为MM,因此sFirstName和sLastName是Detail的子属性。

这个窗口后面还有一个非常简单的代码:

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

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

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

最新更新