ICommand в MVVM WPF - PullRequest
       15

ICommand в MVVM WPF

3 голосов
/ 13 марта 2009

Я смотрю на этот материал MVVM и сталкиваюсь с проблемой.

Ситуация довольно проста.

У меня есть следующий код на моей странице index.xaml

    <Grid>
    <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <view:MovieView ></view:MovieView>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

и в моем index.xaml.cs

...

InitializeComponent (); base.DataContext = new MovieViewModel (ent.Movies.ToList ()); ....

и вот моя MoveViewModel

    public class MovieViewModel
{
    readonly List<Movies> _m;
    public ICommand TestCommand { get; set; }
    public MovieViewModel(List<Movies> m)
    {
        this.TestCommand = new TestCommand(this);
        _m = m;
    }
    public List<Movies> lm
    {
        get
        {
            return _m;
        }
    }
}

наконец

вот мой контроль xaml MovieView

    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"></ColumnDefinition>
        <ColumnDefinition Width="Auto"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Label VerticalAlignment="Center" Grid.Row="0" Grid.Column="0">Title :</Label><TextBlock VerticalAlignment="Center" Grid.Row="0" Grid.Column="1" Text="{Binding Title}"></TextBlock>  
    <Label VerticalAlignment="Center" Grid.Row="1" Grid.Column="0">Director :</Label><TextBlock VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" Text="{Binding Director}"></TextBlock>
    <Button Grid.Row="2" Height="20" Command="{Binding Path=TestCommand}" Content="Edit" Margin="0,4,5,4" VerticalAlignment="Stretch" FontSize="10"/>
</Grid>

Итак, у меня проблема в том, что если я установлю ItemsSource в Binding

ничего не получается

если я установлю ItemsSource = "{Binding lm}"

он заполняет мой itemsControl, но команда (Command = "{Binding Path = TestCommand}") не работает.

Конечно, это не работает, потому что TestCommand не принадлежит моему объекту сущности Movies.

Итак, наконец, мой вопрос,

что мне нужно передать в ItemsControl, чтобы он работал?

Спасибо заранее

Ответы [ 6 ]

4 голосов
/ 13 марта 2009

Как только ваши элементы отображаются, каждому элементу присваивается значение DataContext определенной строки, которую он представляет, поэтому вы больше не можете ссылаться на свой первый DataContext. Кроме того, из-за того, что вы находитесь в DataTemplate, ваши привязки начнут работать, когда в этом шаблоне возникнет необходимость ... поэтому в этом случае вам нужно найти родительский элемент управления через привязку RelativeSource ...

Надеюсь, это кое-что объясняет ..

2 голосов
/ 13 марта 2009

Попробуйте реализовать интерфейс INotifyPropertyChanged:

public class MovieViewModel : INotifyPropertyChanged
{
    readonly List<Movies> _m;
    private ICommand _testCommand = null;
    public ICommand TestCommand { get { return _testCommand; } set { _testCommand = value; NotifyPropertyChanged("TestCommand"); } }
    public MovieViewModel(List<Movies> m)
    {
        this.TestCommand = new TestCommand(this);
        _m = m;        
    }
    public List<Movies> lm
    {
        get
        {
            return _m;
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string sProp)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(sProp));
        }
    }    
}

Что происходит, так это то, что TestCommand имеет значение, а пользовательский интерфейс не получает уведомления о том, что происходит изменение. На элементах управления вы решаете эту проблему с помощью свойств зависимости, для объекта данных вы можете использовать интерфейс INotifyPropertyChanged.

Во-вторых, объекты Movie не имеют ссылки на родительский объект ..

Вы можете решить эту проблему тремя различными способами:

  1. имеет ссылку на модель в Movie и задает путь Bind следующим образом: т.е. если ваше свойство называется ParentMovieModel, то привязка будет выглядеть следующим образом:

    {Binding Path = ParentMovieModel.TestCommand}

  2. Создайте привязку на основе ElementName следующим образом: найдите родительский элемент управления, на котором вы установили свой DataContext, и присвойте ему имя: т.е. Root. Теперь создайте привязку на основе ElementName следующим образом:

    {Binding ElementName = Root, Path = DataContext.TextCommand}

  3. Создайте привязку на основе RelativeSource следующим образом: найдите родительский элемент управления по типу и используйте тот же путь, что и выше ...

    {Binding RelativeSource = {RelativeSource FindAncestor, AncestorType = {x: введите yourparentwindowtype}}, путь = DataContext.TextCommand}

1 голос
/ 02 октября 2010
//include namespace
using Microsoft.Practices.Composite.Wpf.Commands;

readonly List<Movies> _m;
    public ICommand TestCommand { get; set; }
    public MovieViewModel(List<Movies> m)
    {
        this.TestCommand = new DelegateCommand<object>(TestcommandHandler);
        _m = m;
    }
    public List<Movies> lm
    {
        get
        {
            return _m;
        }
    }

void TestcommandHandler(object obj)
{
      // add your logic here
}
}
1 голос
/ 13 марта 2009

все заработало

вот вещь

 <ItemsControl DataContext="{Binding}" ItemsSource="{Binding lm}">

 Command="{Binding Path=DataContext.TestCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" 

поэтому RelativeSource я пропустил.

если бы у кого-нибудь было хорошее объяснение этому, я был бы определенно счастлив.

0 голосов
/ 13 марта 2009

в случае ItemsSource = "{Binding Path = lm}">

itemsControl работает хорошо, но я полностью игнорирую свою MovieViewModel

и я получил это в окне вывода

Ошибка System.Windows.Data: 39: Ошибка пути BindingExpression: свойство 'TestCommand' не найдено в 'объекте' '' Фильмах '(HashCode = 1031007)'. BindingExpression: Path = TestCommand; DataItem = 'Фильмы' (HashCode = 1031007); Целевым элементом является «Кнопка» (Имя = ''); Свойство target - «Команда» (тип «ICommand»)

Фильмы - это объект моей сущности, которому принадлежат только свойства «Заголовок» и «Режиссер»

0 голосов
/ 13 марта 2009

А как же <ItemsControl ItemsSource="{Binding Path=lm}">?

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