簡體   English   中英

將焦點設置到ItemsControl WPF中的項目

[英]Set focus to an item in ItemsControl WPF

我正在scrolviewer中水平顯示圖像列表,並且正在使用下面的代碼行來做到這一點

<ScrollViewer Name="lviewThumbnails" Height="230"   >
<ItemsControl ItemsSource="{Binding ThumbsCollection}"  MouseWheel="ItemsControl_MouseWheel" > 
    <ItemsControl.ItemTemplate >
        <DataTemplate>
            <DockPanel Height="230">
                <Button Name="pageThumbnail" DockPanel.Dock="Top" Tag="{Binding}" VerticalAlignment="Top"  Margin="5,2">
                    <Grid>
                        <Image MaxWidth="140" Height="200" Source="{Binding ThubnailPath,IsAsync=True}" Stretch="None"></Image>                             
                    </Grid>
                </Button>
                <Label  HorizontalAlignment="Center"  FontSize="14" FontWeight="Bold" Content="text" Foreground="White" Padding="5"></Label>
            </DockPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel  Orientation="Horizontal"  />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

我要在打開視圖時將焦點設置到此列表中的特定圖像項,例如,如果列表中有150張圖像,並且想在打開列表時將焦點設置為圖像75例如

我在做什么是在按鈕上單擊,我正在設置此代碼

  lviewThumbnails.Visibility = Visibility.Visible; 

使圖像可見,但是最先選擇的項是每次選擇的默認項。 我正在使用觸發器來檢測選定的圖像

  <DataTrigger Binding="{Binding IsSelected}" Value="True">                                            
                                        <Setter TargetName="pageThumbnail" Property="BorderBrush" Value="Yellow"/>
                                        <Setter TargetName="pageThumbnail" Property="BorderThickness" Value="3"/>
 </DataTrigger>

但是問題是如果圖像75被選中,我可以在圖像75周圍看到黃色邊框,但是當我單擊按鈕時焦點仍然在圖像1上。我必須滾動查看器的上一個,下一個按鈕才能到達圖像75。我正在使用具有特定樣式的滾動查看器,例如第1列,第2列的按鈕內容和第3列的再次按鈕(希望它不會影響默認行為),並且我防止在各處滾動查看器上的鼠標滾動

 <ControlTemplate TargetType="{x:Type ScrollViewer}" x:Key="ButtonOnlyScrollViewer">
        <ControlTemplate.Resources>
        </ControlTemplate.Resources>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20" />
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="20"/>
            </Grid.ColumnDefinitions>
            <Button Style="{StaticResource ResourceKey=ViewPreviousButton}" Grid.Column="0"   Command="ScrollBar.PageUpCommand" MouseWheel="ItemsControl_MouseWheel" 
                      Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></Button>

            <ScrollContentPresenter
            CanContentScroll="{TemplateBinding CanContentScroll}"
            Grid.Column="1" 
            Content="{TemplateBinding Content}"  
            Width="{TemplateBinding Width}"
            Height="{TemplateBinding Height}" 
            Margin="{TemplateBinding Margin}"/>
            <Button Style="{StaticResource ResourceKey=ViewNextButton}" Grid.Column="2"   Command="ScrollBar.PageDownCommand"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MouseWheel="ItemsControl_MouseWheel"
                     ></Button>

        </Grid>
    </ControlTemplate>

您可以使用觸發器來執行此操作,並為所選項目或適合您的方式使用單獨的模板。

假設您具有圖像ID作為屬性,則類似這樣;

<DataTrigger Binding="{Binding ThumbsCollection.ImageId}" Value="75">
   <Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
</DataTrigger>

您可以在這種情況下使用附加屬性FocusManager.FocusedElement

<DataTrigger Binding="{Binding IsSelected}" Value="True">                                            
    <Setter TargetName="pageThumbnail" Property="BorderBrush" Value="Yellow"/>
    <Setter TargetName="pageThumbnail" Property="BorderThickness" Value="3"/>
    <Setter TargetName="pageThumbnail" Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</DataTrigger>

要么

<DataTrigger Binding="{Binding IsSelected}" Value="True">                                            
    <Setter TargetName="pageThumbnail" Property="BorderBrush" Value="Yellow"/>
    <Setter TargetName="pageThumbnail" Property="BorderThickness" Value="3"/>
    <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=pageThumbnail}"/>
</DataTrigger>

如果上述方法無法正確聚焦,則先嘗試聚焦容器,然后聚焦pageThumbnail

<DataTrigger Binding="{Binding IsSelected}" Value="True">                                            
    <Setter TargetName="pageThumbnail" Property="BorderBrush" Value="Yellow"/>
    <Setter TargetName="pageThumbnail" Property="BorderThickness" Value="3"/>
    <Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
    <Setter TargetName="pageThumbnail" Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</DataTrigger>

更新

問題不僅是焦點,而且元素的位置也不在視圖范圍之內

試試這個XAML

<ItemsControl ItemsSource="{Binding ThumbsCollection}"  MouseWheel="ItemsControl_MouseWheel" Name="singleThumbs">
    <ItemsControl.Resources>
        <Style TargetType="ContentPresenter" xmlns:l="clr-namespace:WPFPerfomanceTest">
            <Setter Property="l:ScrollProvider.ScrollIntoView"
                    Value="{Binding IsSelected}" />
        </Style>
    </ItemsControl.Resources>
    <ItemsControl.ItemTemplate >
        <DataTemplate>
            <DockPanel Height="230">
                <Button Name="pageThumbnail"  DockPanel.Dock="Top" Tag="{Binding}" VerticalAlignment="Top"  Margin="5,2" Width="140">
                    <Grid>
                        <Image Height="200" Source="{Binding ThubnailPath,IsAsync=True}" Stretch="None"></Image>                                        
                    </Grid>
                </Button>
                <Label   HorizontalAlignment="Center"  FontSize="14" FontWeight="Bold" Content="{Binding PageNo}" Foreground="White" Padding="5"></Label>
            </DockPanel>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding IsSelected}" Value="True" >
                    <Setter TargetName="pageThumbnail" Property="BorderBrush" Value="Yellow"/>
                    <Setter TargetName="pageThumbnail" Property="BorderThickness" Value="3"/>
                    <Setter TargetName="pageThumbnail" Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
                </DataTrigger>

            </DataTemplate.Triggers>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel  Orientation="Horizontal"  />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

請注意,我為ContentPresenter添加了樣式,並將ScrollProvider.ScrollIntoView綁定到IsSelected屬性。

還從圖像中刪除了最大寬度,並為按鈕指定了Width =“ 140”。 最大寬度會導致按鈕尺寸縮小,直到加載圖像為止,這實際上使視圖帶來的行為無效

並使其正常工作

我們需要一些附加的行為,將此類添加到您的項目中

class ScrollProvider : DependencyObject
{
    public static bool GetScrollIntoView(DependencyObject obj)
    {
        return (bool)obj.GetValue(ScrollIntoViewProperty);
    }

    public static void SetScrollIntoView(DependencyObject obj, bool value)
    {
        obj.SetValue(ScrollIntoViewProperty, value);
    }

    // Using a DependencyProperty as the backing store for ScrollIntoView.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ScrollIntoViewProperty =
        DependencyProperty.RegisterAttached("ScrollIntoView", typeof(bool), typeof(ScrollProvider), new PropertyMetadata(false, OnScrollIntoViewChanged));

    private static void OnScrollIntoViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement element = d as FrameworkElement;
        if ((bool)e.NewValue)
        {
            element.BringIntoView();
            element.Focus();
        }
    }
}

如果要設置焦點或顯示一些效果,可以綁定IsFocus並使用觸發器

private void Button_Click(object sender, RoutedEventArgs e)
        {
            lviewThumbnails.Visibility = Visibility.Visible;

            int index = 75;
            ThumbsCollection[index].IsFocus = true;

            Button button = (Button)FindFirstVisualChild(lviewThumbnails, "pageThumbnail");

            lviewThumbnails.ScrollToHorizontalOffset((button.ActualWidth + 6.5) * index); // set it with pageThumbnail's location or margin
        }

        public object FindFirstVisualChild(DependencyObject obj, string childName)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child.GetValue(NameProperty).ToString() == childName)
                {
                    return child;
                }
                else
                {
                    object childOfChild = FindFirstVisualChild(child, childName);
                    if (childOfChild != null)
                    {
                        return childOfChild;
                    }
                }
            }
            return null;
        }

我想您想在屏幕上顯示第75個(中間項目)項目,因此可以使用ScrollToHorizontalOffset 首先獲取按鈕的actualwith,然后在計算中獲取按鈕的邊距/邊距,然后獲取偏移量。

所有這些答案都忽略了有關ItemsControls的令人討厭的關鍵信息。 他們使用虛擬化,因此只有視圖中實際存在的項目(以及周圍的一些項目)才真正“存在”。 使用上面給出的答案,OP試圖執行的操作是不可能的,因為第75張圖像實際上還不存在,因此您無法將焦點設置在它上面。

你需要:

1)訂閱ItemsControl ItemContainerGenerator.StatusChanged事件2)設置滾動位置,以便將第75個項目滾動到視圖中3)在StatusChanged事件處理程序中,等待狀態= ContainerGenerated以獲得第75個項目,然后退訂並設置焦點

是的,這太復雜了,是的,代碼將“立即”執行,但是您必須等到生成容器后,第75個項目才能對其進行設置。 虛擬化就是這樣工作的。

當您僅創建項目1-10時,您正在嘗試將焦點設置到第75個項目。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM