Выполнить метод в пользовательском контроле MVVM - PullRequest
4 голосов
/ 08 августа 2011

Я работаю над своим первым приложением MVVM и не могу заставить его работать должным образом.

В моем главном окне у меня есть кнопка, которая выполняет команду SQL, которая возвращает объект пользовательского типа таблицы данных.

Окно также содержит пользовательский элемент управления, который состоит из нескольких заголовков столбцов и оконных форм, размещенных в DataGridView. Мне нужно как-то сказать пользовательскому элементу управления выполнить метод, который передает данные в DataGridView, чтобы он мог обновлять свои значения.

Я попытался создать свойство зависимости в моем элементе управления WPF Grid, которое привязано к данным моей модели представления, но оно не обновляется должным образом.

Как мне заставить это работать?

- EDIT -

Вот XAML для моего пользовательского контроля LiteGrid -

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

Моя модель основного вида:

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>

Ответы [ 2 ]

4 голосов
/ 08 августа 2011

Поскольку у вас есть 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 в MainViewModel, поскольку оно должно храниться в LiteGridViewModel, а не MainViewModel

И в вашей MainWindowViewModel работе с LiteGridViewModel вместопытаясь работать с ViewModel через View

Grid = new LiteGridViewModel();

void _source_DataArrived(LiteTable data)
{
    Grid.Data = data;  // Fill property in ViewModel
    Grid.UpdateData(); // Call command on ViewModel
}
0 голосов
/ 08 августа 2011
public LiteTable Data
{
    get { return (LiteTable)GetValue(DataProperty); }
    set 
    {
        object oldvalue = Data;
        SetValue(DataProperty, value);
        OnPropertyChanged(new DependencyPropertyChangedEventArgs(DataProperty, oldvalue, value));
    }
}

// Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
    DependencyProperty.Register("Data", typeof(LiteTable), typeof(LiteGrid), new UIPropertyMetadata(null));

попробуйте это ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...