繁体   English   中英

MVVM WPF中的ICommand

[英]ICommand in MVVM WPF

我正在看这些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 =新的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>

所以我的问题是,如果我在Binding中设置ItemsSource

它什么也没做

如果我设置ItemsSource =“ {Binding lm}”

它填充了我的itemsControl,但命令(Command =“ {Binding Path = TestCommand}”)不起作用。

当然,它不起作用,因为TestCommand不属于我的实体对象Movies。

所以最后我的问题是

我需要传递给ItemsControl使其工作吗?

提前Thx

呈现项目后,每个项目都将设置为它代表的特定行的DataContext,因此您将不再能够引用您的第一个DataContext。此外,由于您位于DataTemplate中,因此您的绑定将在需要该模板时开始工作..因此,在这种情况下,您需要通过RelativeSource绑定查找父控件...

希望能解释一些事情。

尝试实现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具有一个值,并且UI没有收到有关更改发生的通知。在控件上,您可以使用Dependency属性解决此问题,在数据对象上,可以使用INotifyPropertyChanged接口。

其次,Movie对象没有对父对象的引用。

您可以通过三种不同的方式解决此问题:

  1. 在Movie上具有对模型的引用,并进行如下绑定路径:即..如果您的属性名为ParentMovieModel,则您的Binding将类似于:

    {Binding Path = ParentMovieModel.TestCommand}

  2. 像这样基于ElementName进行绑定:在设置DataContext的位置找到父控件,并为其命名:Root。 现在基于ElementName创建一个绑定,如下所示:

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

  3. 像这样基于RelativeSource进行绑定:按类型查找父控件,并使用与上面相同的路径...

    {Binding RelativeSource = {RelativeSource FindAncestor,AncestorType = {x:Type yourparentwindowtype}},Path = DataContext.TextCommand}

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

工作正常

这是东西

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

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

所以RelativeSource是我想念的东西。

如果有人对此有很好的解释,我一定会很高兴。

<ItemsControl ItemsSource="{Binding Path=lm}">呢?

在ItemsSource =“ {Binding Path = lm}”>情况下

itemsControl运作良好,但我无法绕过我的MovieViewModel

我在输出窗口中得到了这个

System.Windows.Data错误:39:BindingExpression路径错误:在“对象”“电影”(HashCode = 1031007)上找不到“ TestCommand”属性。 BindingExpression:Path = TestCommand; DataItem ='电影'(HashCode = 1031007); 目标元素是'Button'(Name =''); 目标属性为“命令”(类型为“ ICommand”)

电影是我的实体对象,并且仅拥有Title和Director属性

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM