【问题标题】:Bind ViewModel to Item from LongListSelector in DataTemplate从 DataTemplate 中的 LongListSelector 将 ViewModel 绑定到 Item
【发布时间】:2013-01-29 15:34:58
【问题描述】:

我想在 LongListSelector 中显示对象列表,并使用 DataTemplate 对其进行格式化。为了正确使用 MVVM,我想在这个 DataTemplate 中有一个 ViewModel。

这个ViewModel的创建没有问题,但是如何将Item传递给ViewModel呢?

我正在使用此代码:

<Controls:LongListSelector 
     ItemsSource="{Binding MyItems}" Margin="0" HorizontalAlignment="Stretch" 
                           HorizontalContentAlignment="Stretch" >
    <Controls:LongListSelector.DataContext>
        <viewmodel:MyListOfItemsViewModel />
    </Controls:LongListSelector.DataContext>
 <Controls:LongListSelector.ItemTemplate>
        <DataTemplate>
            <StackPanel x:Name="CurTemplate">
                <Grid Margin="10" >
                    <Grid.DataContext>
                        <viewmodel:MyViewModel MyItem="{Binding Path=DataContext,ElementName=CurTemplate}" />
                    </Grid.DataContext>

但是很可惜,为 MyItem 设置的唯一内容是 null,并且永远不会更新为实际值。我发现在这个过程的后期(在MyItem CurTemplate 的初始设置之后确实有一个有效的DataContext,但这并没有发送到我的ViewModel。我在这里遗漏了什么吗?

为了完整起见,MyViewModel 的代码:

public static DependencyProperty MyItemProperty = DependencyProperty.Register("MyItem", typeof(object), typeof(MyViewModel), new PropertyMetadata("asd", ItemChanged));

    private static void ItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
       System.Diagnostics.Debugger.Break(); // to set when something is set
       // called once, NewValue is null
    }

    public object MyItem
    {
        get
        {
            return (object)GetValue(MyItemProperty);
        }
        set
        {
            SetValue(MyItemProperty, value);
            RaisePropChangeEvent("MyItem");
        }
    }

我做了很多搜索和摆弄,但我很确定这只是这里缺少的一件小事。如果你能在这里帮助我,我会很高兴...

编辑:已解决

我通过使用{Binding Path=Content,RelativeSource={RelativeSource Mode=TemplatedParent}} 作为视图模型的绑定解决了我的问题。我不知道为什么这适用于Content,但不适用于DataContext...

感谢您的帮助,robertftw,您的链接帖子让我走上了正轨!

【问题讨论】:

    标签: c# xaml data-binding windows-phone-8


    【解决方案1】:

    好像我几天前遇到的问题: Binding does not update usercontrol property correctly MVVM

    public static DependencyProperty MyItemProperty = DependencyProperty.Register("MyItem", typeof(object), typeof(MyViewModel), new PropertyMetadata(string.Empty, ItemChanged));
     private static void ItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
            var obj = d as MyViewModel;
            obj.RaisePropChangeEvent("MyItem");
    }
    

    我遇到的问题是 MyItem 的集合实际上没有被调用。

    【讨论】:

    • 感谢您抽出宝贵时间回答,但我已经知道并考虑到了这一点;-) 问题是 ItemChanged 只被调用一次(带有 null),并且 DataContext 永远不会被发送下来初始化后从 StackPanel...
    【解决方案2】:

    你想做什么? 您是否只想与选择更改进行交互并将 LongListSelector 中的选定项目推送到 ViewModel?

    如果是这样...我正在为这种情况使用扩展程序。这种扩展的唯一作用是从 ViewModel 设置当前项目不会移植回视图(但不需要)。

    ViewModel 的变化是

    public RelayCommand<MyItemType> ViewModelCommand
    

    XAML 更改是

    <phone:LongListSelector extensions:LongListSelectorExtension.Command="{Binding ViewModelCommand}" />
    

    扩展

    public static class LongListSelectorExtension
    {
    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.RegisterAttached("Command",
            typeof(ICommand), typeof(LongListSelectorExtension),
            new PropertyMetadata(null, OnCommandChanged));
    
    public static ICommand GetCommand(LongListSelector selector)
    {
        return (ICommand)selector.GetValue(CommandProperty);
    }
    
    public static void SetCommand(LongListSelector selector, ICommand value)
    {
        selector.SetValue(CommandProperty, value);
    }
    
    private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var selector = d as LongListSelector;
        if (selector == null)
        {
            throw new ArgumentException(
                "You must set the Command attached property on an element that derives from LongListSelector.");
        }
    
        var oldCommand = e.OldValue as ICommand;
        if (oldCommand != null)
        {
            selector.SelectionChanged -= OnSelectionChanged;
        }
    
        var newCommand = e.NewValue as ICommand;
        if (newCommand != null)
        {
            selector.SelectionChanged += OnSelectionChanged;
        }
    }
    
    private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var selector = sender as LongListSelector;
        var command = GetCommand(selector);
    
        if (command != null && selector.SelectedItem != null)
        {
            command.Execute(selector.SelectedItem);
        }
    
        selector.SelectedItem = null;
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-19
      • 2012-04-21
      • 2021-10-25
      • 1970-01-01
      • 1970-01-01
      • 2016-01-11
      • 2017-04-07
      • 2011-05-03
      相关资源
      最近更新 更多