【问题标题】:CurrentPosition property not being updated properlyCurrentPosition 属性未正确更新
【发布时间】:2011-07-31 00:45:01
【问题描述】:

让我再试一次...这里是 XAML。您可以看到 CollectionViewSource、将其用作 DataContext 的 Grid、ListView 和 Delete 按钮。发生的事情是,当我单击 ListView 中的一行(并且触发样式触发器以选择 ListViewItem)时,该行被选中。当我单击删除按钮时,onclick 会触发,但 CurrentPosition 属性设置为 -1。是什么阻止了 CurrentPosition 属性被更新。

XAML

<Window x:Class="PretzelsUI.Admin.Ovens"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="" 
    Height="344" 
    Width="474" 
    mc:Ignorable="d" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:my="clr-namespace:Pretzels.Model;assembly=Pretzels.Model"
    ResizeMode="NoResize"
    WindowStartupLocation="CenterOwner"
    Background="{StaticResource WindowGradient}"       
    Loaded="Window_Loaded">
<Window.Resources>
    <CollectionViewSource x:Key="ovenViewSource" d:DesignSource="{d:DesignInstance my:Oven, CreateList=True}" />
</Window.Resources>
<Grid DataContext="{StaticResource ovenViewSource}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Border Grid.Row="0" BorderBrush="{StaticResource formTitleBorderBrush}" BorderThickness="2" Name="border1" CornerRadius="30" Padding="7" Background="{StaticResource formTitleBackgroundBrush}" VerticalAlignment="Center" Margin="11">
        <TextBlock Name="textBlock1" Text="Ovens" FontSize="18" FontWeight="Bold" Foreground="{StaticResource formTitleForegroundBrush}" />
    </Border>
    <ListView IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}" Name="ovenListView" SelectionMode="Single" Height="177"  Grid.Row="1" TabIndex="2" Margin="5,5,5,0">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="Control.HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="Control.VerticalContentAlignment" Value="Stretch" />
                <!--<Style.Triggers>
                    <Trigger Property="IsKeyboardFocusWithin" Value="True">
                        <Setter Property="IsSelected" Value="True" />
                    </Trigger>
                </Style.Triggers>-->
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.View>
            <GridView>                    
                <GridViewColumn x:Name="nameColumn" Header="Name" Width="100">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox Margin="-6,-1" Text="{Binding Path=OvenName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true, UpdateSourceTrigger=PropertyChanged}" Width="Auto" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn x:Name="descriptionColumn" Header="Description" Width="300">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox Margin="-6,-1" Text="{Binding Path=OvenDescription, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" Width="Auto" MaxLength="100"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
    <StackPanel Grid.Row="2" Name="stackPanel2" Margin="0,30,0,0" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
        <Button Content="New" Height="23"  Margin="2,0,2,0" TabIndex="3" Name="btnAdd" Width="75" Click="btnInsrt_Click" />
        <Button Content="Save" Height="23" Margin="2,0,2,0" TabIndex="4" Name="btnSave" Width="75" Click="btnSave_Click" />
        <Button Content="Delete" Height="23" Margin="2,0,2,0" TabIndex="5" Name="btndelete" Width="75" Click="btndelete_Click" />
    </StackPanel>
</Grid>

C#

 public partial class Ovens : Window
{
    private PretzelEntities dbcontext = new PretzelEntities();
    //private OvenCollection EntityData;
    private CollectionViewSource ViewSource;
    private BindingListCollectionView OvenView;

    public Ovens()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        ViewSource = (CollectionViewSource)this.FindResource("ovenViewSource");

        ViewSource.Source = from s in dbcontext.Ovens select s;
        OvenView = (BindingListCollectionView)(ViewSource.View);
    }


    private void btndelete_Click(object sender, RoutedEventArgs e)
    {
            if (OvenView.CurrentPosition > -1)
            {
                if (MessageBox.Show("Do you really want to delete this Oven?", "Delete Confirmation", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    this.OvenView.RemoveAt(this.OvenView.CurrentPosition);
                }
            }
            else
            {
                MessageBox.Show("Nothing to Delete.", "Error", MessageBoxButton.OK);
            }
    }




enter code here

我认为发生的情况是,当触发器触发 ListCollectionView 的 CurrentItem/CurrentPosition 时,没有正确更新。当我单击其中一行中的文本框时,我不确定是否手动执行此操作(尽管我知道可用的方法)。不知道该怎么做,我可能只是使用 VisualTreeHelper 手动定位选定的 ListViewItem。

【问题讨论】:

  • 您确定 ListView 绑定到 same 集合视图吗?我们无法从您发布的代码中看出。
  • 同意,这里有很多可能是错误的。我现在看不出这段代码可能连接到正确的源代码。
  • 我相信是的。该页面在 Windows.Resources (ovenViewSource) 中有一个 CollectionViewSource 上面显示的 ListView 位于 Grid () 内。如果我还没有提供所有信息,请告诉我
  • 目前,这个 ListView 将绑定到它的父级的任何数据上下文,我们无法从这里判断。如果它没有被设置,那么就没有什么可以绑定的了。如果是,那将有助于了解上下文是什么。
  • 抱歉...我已更新以包含所有 XAML/C#...希望你们能指出我哪里出错了 :)

标签: c# wpf listview binding wpf-controls


【解决方案1】:

我终于放弃了样式触发器,只为 ListView 行内的文本框/组合框处理了 GotFocus 事件。在处理程序中,我能够获取 ListViewItem 并将 IsSelected 设置为 true。像冠军一样工作。

private void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        Control ctrl = sender as Control;
        ContentPresenter cp = (ContentPresenter)ctrl.TemplatedParent;
        GridViewRowPresenter gp = (GridViewRowPresenter)cp.Parent;
        Grid g = (Grid)gp.Parent;
        ListViewItem lvi = (ListViewItem)g.TemplatedParent;
        lvi.IsSelected = true;
    }

【讨论】:

    【解决方案2】:

    做了一些测试,问题出在样式触发器上。

    <Trigger Property="IsKeyboardFocusWithin" Value="True">
                            <Setter Property="IsSelected" Value="True" />
                        </Trigger>
    

    当我单击 ListViewItem 内的任何内容(即 TextBox/ComboBox)时,我正在使用样式触发器来选择 ListViewItem。当此触发器到位时,如果我选择一个 TextBox,则行选择,但 ListCollectionView 的 CurrentPosition 始终为 -1。如果我删除触发器并实际选择行本身(单击文本框外),则 CurrentPosition 设置正确。我的问题是为什么...我需要手动设置 CurrentPosition。任何帮助表示赞赏。

    【讨论】:

      【解决方案3】:

      IMO,最好像这样在代码中设置这一切:

      void InitializeDataContext()
      {
          var ovens = (from s
                       in dbcontext.Ovens
                       select s).ToList();
      
          ICollectionView view = new CollectionViewSource
          {
              Source = ovens
          }.View;
      
          ViewSource = view;
          ovenListView.ItemsSource = ViewSource;
      }
      

      您可以在 Window_Loaded 中调用该方法,消除 Window_Loaded 中的其他代码,然后消除绑定,因为您已经在代码中完成了这一切。在视图 (MVVM) 中没有任何代码的情况下设置这一切确实会更好,但这超出了这个问题的范围。

      【讨论】:

      • 按照建议进行设置,当我选择 ListItem 行之一时,CurrentPosition 仍设置为 -1。当我最初打开窗口并且不单击任何行尝试删除第一行时,它已正确设置.... CurrentPosition 按预期设置为 0。当我单击一行并且样式触发器触发时,该属性没有得到更新。
      • 您根本不需要那种样式触发器。这一切都应该由 WPF 使用 IsSyncronizedWithCurrentItem 和 ICollectionView 自动处理。
      猜你喜欢
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-07
      相关资源
      最近更新 更多