我正在开发我的第一个 MVVM 应用程序,但无法使其正常工作。
在我的主窗口中,我有一个按钮可以执行返回自定义数据表类型对象的 SQL 命令。
该窗口还包含一个用户控件,该控件由一些列标题和一个 Windows 窗体托管的 DataGridView 组成。我需要以某种方式告诉用户控件执行将数据传递给 DataGridView 的方法,以便它可以更新它的值。
我尝试在我的 WPF 网格控件上创建一个依赖属性,该控件绑定(bind)到我的 View 模型的数据,但它没有正确更新。
我怎样才能让它工作?
--编辑--
这是我的 LiteGrid 用户控件的 XAML -
<UserControl x:Class="ReportUtility.Controls.LiteGrid.LiteGrid"
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:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:lite="clr-namespace:ReportUtility.Controls.LiteGrid"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ScrollViewer x:Name="_scroll" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden">
<ItemsControl ItemsSource="{Binding Columns}" Grid.Row="0" Background="AliceBlue">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
<WindowsFormsHost Background="White" Grid.Row="1">
<lite:LiteGridView x:Name="_liteGridView"/>
</WindowsFormsHost>
</Grid>
我的主要 View 模型是:
public class MainWindowViewModel : DependencyObject
{
private readonly ILiteTableSource _source;
public ICommand ExecuteQueryCommand { get; set; }
public LiteGridViewModel Grid { get; set; }
public string SqlCommandText { get; set; }
public MainWindowViewModel(ILiteTableSource source)
{
this.ExecuteQueryCommand = new ExecuteQueryCommand(this);
_source = source;
_source.DataArrived+=new Action<DataSources.LiteSource.LiteTable>(_source_DataArrived);
}
public void ExecuteQuery()
{
_source.Connection = new ServerConnection();
_source.CommandText = this.SqlCommandText;
_source.ExecuteQuery();
}
public LiteTable Results
{
get { return (LiteTable)GetValue(ResultsProperty); }
set { SetValue(ResultsProperty, value); }
}
// Using a DependencyProperty as the backing store for Results. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ResultsProperty =
DependencyProperty.Register("Results", typeof(LiteTable), typeof(MainWindowViewModel), new UIPropertyMetadata(null));
void _source_DataArrived(LiteTable data)
{
this.Results = data;
}
}
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Content="TestButton" HorizontalAlignment="Stretch" Command="{Binding ExecuteQueryCommand}"/>
<TextBox Grid.Row="1" Text="{Binding Path=SqlCommandText, UpdateSourceTrigger=PropertyChanged}"/>
<lite:LiteGrid Grid.Row="2" Data="{Binding Data, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
最佳答案
因为你有一个 LiteGridViewModel
和你的LiteGrid
一起去,为什么不直接从 ViewModel 执行命令?
使用您问题中发布的代码,我会:
将此添加到资源以确保 LiteGridViewModel
使用 LiteView
绘制
<Window.Resources> <!-- Or Grid.Resources if you prefer -->
<DataTemplate DataType="{x:Type lite:LiteGridViewModel}">
<lite:LiteGrid />
</DataTemplate>
</Window.Resources>
替换 <lite:LiteGrid ... />
控制在 MainView
使用 ContentControl 来显示 ViewModel
<ContentControl Content="{Binding Grid}" />
删除 Data
属性(property)上MainViewModel
因为它应该存储在 LiteGridViewModel
中, 不是 MainViewModel
在你的MainWindowViewModel
使用 LiteGridViewModel
而不是尝试通过 View 使用 ViewModel
Grid = new LiteGridViewModel();
void _source_DataArrived(LiteTable data)
{
Grid.Data = data; // Fill property in ViewModel
Grid.UpdateData(); // Call command on ViewModel
}
关于c# - 用户控制 MVVM 中的执行方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6986404/