4

我正在创建一个ListView可以从中删除一些项目(它是收藏夹列表)的方法,方法是选择它们,打开应用栏并单击“从收藏夹中删除”。单击按钮时,会要求当前视图模型中的方法从列表中删除该项目。发生这种情况后,UI 会更新,并且项目会被删除。

现在,我有两个问题。第一个是当一个项目被删除时,页面的后退按钮接收焦点(它得到一个虚线轮廓),这是我不想要的。

第二个问题是列表没有使用我设置的添加/删除动画。

将不胜感激任何一个解决方案。

下面是一些伪代码,显示发生了什么:

XAML:

<GridView x:Name="FavoritesGridView"
    Grid.Row="1"
    SelectionMode="Multiple"
    ItemTemplate="{StaticResource FavoritesOnSectionViewItemTemplate}"
    ItemsSource="{Binding FavoritesList}" 
    ItemClick="ProgramGrid_OnItemClick" 
    IsItemClickEnabled="True"
    SelectionChanged="FavoritesGridView_OnSelectionChanged"
    ScrollViewer.HorizontalScrollMode="Disabled">
    <GridView.ItemContainerStyle>
      <Style TargetType="Control">
        <Setter Property="Margin" Value="0,0,38,8"/>
      </Style>
    </GridView.ItemContainerStyle>
    <GridView.ItemContainerTransitions>
      <TransitionCollection>
        <AddDeleteThemeTransition/>
      </TransitionCollection>
    </GridView.ItemContainerTransitions>
    <GridView.ItemsPanel>
      <ItemsPanelTemplate>
        <WrapGrid Orientation="Vertical" MaximumRowsOrColumns="9" />
      </ItemsPanelTemplate>
    </GridView.ItemsPanel>
</GridView>

代码隐藏:

private void UnFavoriteButton_Click(object sender, RoutedEventArgs e)
{          
    viewModel.RemoveFromFavorites(FavoritesGridView.SelectedItems.Cast<FavoriteProgram>().AsEnumerable());
}

视图模型:

public void RemoveFromFavorites(IEnumerable<FavoriteProgram> programs)
{
    FavoriteController.RemoveFromFavorites(programs);
    UpdateUi();
}

private void UpdateUi()
{
    OnPropertyChanged("FavoritesList");
}

public IEnumerable<FavoriteProgram> FavoritesList
{
    get { return CoreData.TvFavorites; } // A centralized list
}

收藏夹控制器:

public static void RemoveFromFavorites(IEnumerable<FavoriteProgram> programs)
{
    if (programs.IsNullOrEmpty()) return;
    foreach (var program in programs)
        RemoveFromFavorites(program);
}

public static void RemoveFromFavorites(FavoriteProgram program)
{
    if (!IsFavorite(program)) return;

    var list = CoreData.TvFavorites.ToList();
    list.Remove(program);
    CoreData.TvFavorites = list.AsEnumerable();
}

有任何想法吗?

4

2 回答 2

3

I see. So you have two problems.

[1]. The back button receives focus.

It is my opinion that the Back button should never receive focus. There is already a key gesture to go back, so setting focus is silly. Why it wasn't already disabled to have focus, I do not know. Here's all you do:

<Button TabIndex="-1" Style="{StaticResource BackButtonStyle}" />

Or you can do it with a style:

<Grid Background="Black">
    <Grid.Resources>
        <Style TargetType="Button" BasedOn="{StaticResource BackButtonStyle}" x:Name="MyBackButtonStyle">
            <Setter Property="TabIndex" Value="-1" />
        </Style>
    </Grid.Resources>
    <Button Style="{StaticResource MyBackButtonStyle}" />
</Grid>

Using this new style (or just updating the existing one) will result in the back button never receiving focus. If you want it to be able to receive focus, for some reason, then the solution would be to handle the GotFocus event and simply use (sender as Button).Focus(FocusState.Unfocused);. To be fair, you should also determine why you would be removing focus.

[2]. The animations are not happening

This is a common problem. The reason is, you do not want to setup animations on the ListView, you want to set up the animations on the ListView ItemsPanel. Here's all you want to do:

<ListView>
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel>
                <StackPanel.ChildrenTransitions>
                    <AddDeleteThemeTransition />
                </StackPanel.ChildrenTransitions>
            </StackPanel>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

It's as simple as that. (my sample is a StackPanel, remember to use a WrapGrid as you have in your code) You just had the transitions in the wrong place. So, now you can handle the focus problem you are having and you can get the transitions you want.

I might offer a bit of advice. Since you are using view models, it sounds strange to hear that you are not also using delegate commands. If you want to use MVVM at its best, delegate commands solve a lot of problems for you. Read here: http://blog.jerrynixon.com/2012/08/most-people-are-doing-mvvm-all-wrong.html

And for a second bit of advice. It sounds to me like you might be using the default templates from Visual Studio. Most developers start there. The problem is that those templates are not very great to teach best practices. My suggestion: don't be afraid of the blank template.

Best of luck!

于 2013-05-08T18:43:51.193 回答
2

现在,我有两个问题。第一个是当一个项目被删除时,页面的后退按钮接收焦点(它得到一个虚线轮廓),这是我不想要的。

这个问题可以通过在 GridView 的 SelectedItem 属性中添加一个 TwoWay-Binding 来解决。删除最喜欢的程序后,为每个代码设置 SelectedItem,以便它集中在 GridView 中。

XAML:

<GridView x:Name="FavoritesGridView"
          SelectedItem="{Biding SelectedFavorite, Mode=TwoWay}" />

C#:

private FavoriteProgram _selectedFavorite;

public FavoriteProgram SelectedFavorite {
  get {
    return _selectedFavorite;
  }
  set {
    _selectedFavorite = value;
    OnPropertyChanged("SelectedFavorite");
  }
}

删除项目后,将属性 SelectedFavorite 设置为收藏夹列表中的项目。

public void RemoveFromFavorites(IEnumerable<FavoriteProgram> programs) {
  FavoriteController.RemoveFromFavorites(programs);

  UpdateUi();

  SelectedItem = FavoritesList.FirstOrDefault(); // selects the first element in list.
}

第二个问题是列表没有使用我设置的添加/删除动画。

这里的问题是,在您删除收藏夹后,您总是为您的属性使用新的集合/列表CoreData.TvFavorites,因此 GridView 无法确定哪些项目已被删除或添加。

对于绑定场景,有一个名为的专用集合ObservableCollection<T>,它实现了接口INotifyCollectionChanged。该接口定义了一个事件来通知(UI 元素)从集合中添加或删除项目。您应该更改您的属性 FavoritesList 以ObservableCollection<FavoriteProgramm>在 UpdateUI 方法中键入和更新集合以删除相关的收藏夹。

private void UpdateUi()
{ 
   //Update your FavoritesList to enable animations.
    OnPropertyChanged("FavoritesList");
}

private ObservableCollection<FavoriteProgram> _favorites;
public ObservableCollection<FavoriteProgram> FavoritesList
{
  get { 
    if (_favorites == null) {
      _favorites = new ObservableCollection<FavoriteProgram>();
    }

    return _favorites; 
  }
}
于 2013-05-07T06:55:44.543 回答