【问题标题】:How to select an item in LongListSelector using the MVVM-pattern?如何使用 MVVM 模式在 LongListSelector 中选择一个项目?
【发布时间】:2013-10-16 15:27:03
【问题描述】:

我正在使用 MVVM 模式构建应用程序。单击其中一个元素后,我想查看该元素的详细信息。我是这样写的:

XAML

<phone:LongListSelector ItemsSource="{Binding Data}" 
                        Margin="0,0,0,158"
                        SelectedItem="{Binding SelectedItem}">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Button>
                <!-- Command="{Binding ShowDetailsAction}"-->
                    <Button.Template>
                        <ControlTemplate>
                            <TextBlock Text="{Binding Text}"></TextBlock>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
            </StackPanel>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

视图模型:

public IEnumerable SelectedItem
{
    get { return _itemsControl; }
    set
    {
        if (_itemsControl == value)
            return;
        _itemsControl = value;

        // Test
        _mss.ErrorNotification("fd");
    }
}

我也尝试过使用命令,但也没有用。

这是命令部分:

public ICommand ShowDetailsCommand { get; private set; }

public ViewModel()
{
    _loadDataCommand = new DelegateCommand(LoadDataAction);
    SaveChangesCommand = new DelegateCommand(SaveChangesAction);
    ShowDetailsCommand = new DelegateCommand(ShowDetailsAction);
}

private void ShowDetailsAction(object p)
{
    _mss.ErrorNotification("bla bla");
}

编辑

视图模型

private IEnumerable _itemsControl;
public IEnumerable Data
{
  get
  {
    return _itemsControl;
  }
  set
  {
    _itemsControl = value;
    RaisePropertyChanged("Data");
  }
}

protected void RaisePropertyChanged(string propertyName)
{
  PropertyChangedEventHandler handler = PropertyChanged;
  if (handler != null)
    {
      handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

型号

public string Text { get; set; }
public DateTimeOffset Data { get; set; }

EDIT2

private MobileServiceCollection<ModelAzure, ModelAzure> _items;
        private readonly IMobileServiceTable<ModelAzure> _todoTable = App.MobileService.GetTable<ModelAzure>();


private async void RefreshTodoItems()
{
   try
    {
        _items = await _todoTable.ToCollectionAsync();
    }
   catch (MobileServiceInvalidOperationException e)
     {
          _mss.ErrorNotification(e.ToString());
     }
   Data = _items;
}

【问题讨论】:

  • 您是否尝试过在 TwoWay 模式下明确定义您与 SelectedItem 的绑定? (尝试 SelectedItem="{Binding SelectedItem, Mode=TwoWay}")
  • 我添加了 Mode=TwoWay 但不起作用。
  • 您能否提供更多视图模型的代码?查看您的 Data 属性及其内容类型可能会很有用。

标签: c# silverlight button mvvm longlistselector


【解决方案1】:

您的Data 属性看起来像

private MobileServiceCollection<ModelAzure, ModelAzure> _itemsControl;
public MobileServiceCollection<ModelAzure, ModelAzure> Data
{
  get
  {
    return _itemsControl;
  }
  set
  {
    _itemsControl = value;
    RaisePropertyChanged("Data");
  }
}

已编辑

似乎是SelectedItem property from LongListSelector cannot be bound in WP8。 你可以做的是:

  • 使用上面链接中提供的派生和固定的自定义 LongListSelector,而不是默认的,如下所示:

    public class LongListSelector : Microsoft.Phone.Controls.LongListSelector
    {
        public LongListSelector()
        {
            SelectionChanged += LongListSelector_SelectionChanged;
        }
    
        void LongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SelectedItem = base.SelectedItem;
        }
    
        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register(
                "SelectedItem",
                typeof(object),
                typeof(LongListSelector),
                new PropertyMetadata(null, OnSelectedItemChanged)
            );
    
        private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var selector = (LongListSelector)d;
            selector.SelectedItem = e.NewValue;
        }
    
        public new object SelectedItem
        {
            get { return GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }
    }
    
  • 从 LongListSelector 注册 SelectionChanged 事件并在关联的处理程序/回调中自行调用您的 ViewModel:

在你看来:

<phone:LongListSelector x:Name="YourLongListSelectorName"
                        ItemsSource="{Binding Data}" 
                        Margin="0,0,0,158"
                        SelectionChanged="OnSelectedItemChanged">

在你的代码后面:

private void OnSelectedItemChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs e)
{
    ((YourViewModel)this.DataContext).NewSelectedItemMethodOrWhateverYouWant((ModelAzure)this.YourLongListSelectorName.SelectedItem);
    //or
    ((YourViewModel)this.DataContext).SelectedItem = (ModelAzure)this.YourLongListSelectorName.SelectedItem;
}

最后你的Button 命令不能正常工作,因为当你使用DataTemplate 时,环境DataContext 就是项目本身。这意味着它正在寻找您的 Command 到您的 Model 实例,而不是您的 ViewModel 实例。

希望对你有帮助

【讨论】:

  • 我不确定.. 但 _itemsControl 不能同时是 IEnumerable 和 Model 的类型。
  • SelectionChanged="OnSelectedItemChanged"
  • 我创建了方法:internal void Selected(object p) { Debug.WriteLine(p); } 和输出只是:PanoramaITWEM.Model.ModelAzure
  • 是内部 void Selected(object p) { Debug.WriteLine(p);一个 ViewModel 方法?如果是这样,对我来说这似乎很正常。您正在分配 Data = _items; (代码取自 EDIT2),_items 的类型为 MobileServiceCollection。所以基本上 _items 是 ModelAzure 实例的集合,选择其中的一个项目,会给你一个 ModelAzure 实例。只需将 p 转换为 ModelAzure 即可访问其属性。代码更新
  • 也许这是个愚蠢的问题,也许我很累或者不知道该怎么做......但是对象是模型类型。我不知道如何获得例如 Text 值。
【解决方案2】:

在您的 ViewModel 中,您有:

public IEnumerable SelectedItem
{
get { return _itemsControl; }
set
{
    if (_itemsControl == value)
        return;
    _itemsControl = value;

    // Test
    _mss.ErrorNotification("fd");
}

}

为什么您的 SelectItem 是 IEnumerable?它不应该是“模型”类型吗?您的列表绑定到“数据”,它应该是 ObservableList,而不是 IEnumerable。它会提供自己的更改通知,所以你不需要。

列表被选中时会设置SelectedItem,但如果类型错误则不会被设置。

格雷格

【讨论】:

  • 因为我正在从 Azure 读取数据。将数据加载到 IEnumerable 比 Observable 更容易......我在帖子中添加了更多代码
猜你喜欢
  • 2011-02-23
  • 1970-01-01
  • 2011-06-24
  • 2019-12-17
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
  • 2022-11-16
相关资源
最近更新 更多