2017-07-27 58 views
0

我正在努力實現實現FocusVisualStyle用鼠標和鍵盤焦點

爲簡單起見,我有單元網格,我嘗試添加的FocusVisualStyle虛線矩形到每個細胞,當它是聚焦。然而,只有當元素被導航到使用鍵盤時,樣式才適用。我期望達到相同的效果,但它可以使用鍵盤焦點鼠標焦點(單擊單元格時)。

我曾嘗試

我看着用容器像一個Border,但沒有虛線,試圖使用過的元素虛線矩形中,它的位置,但這是提供不一致結果。我還嘗試將觸發器附加到單元格的IsFocused屬性,但該屬性僅適用於Keyboard Focus。

目前代碼

現在我有(一StackPanel)設置爲細胞活動,使得通過網格我的自定義導航。我目前的「視覺風格」是將背景更改爲適用於鼠標和鍵盤焦點的顏色。我正在爲單元格周圍的虛線矩形替換背景更改,但我嘗試的XAML不起作用,因爲FocusVisualStyle僅適用於鍵盤焦點。

這是我的XAML和一個簡化版本C#的是我曾嘗試

XAML

<!-- The "cell" I'm trying to acheive a dashed border around --> 
<StackPanel x:Key="ContactCell" 
      Focusable="True" 
      GotFocus="StackPanel_GotFocus" 
      LostFocus="StackPanel_LostFocus" 
      PreviewMouseDown="Contact_Select" 
      Style="{DynamicResource ContactFocusStyle}"> 
    <!-- other children in here --> 
</StackPanel> 

<Style x:Key="ContactFocusStyle" TargetType="StackPanel"> 
     <Style.Triggers> 
      <Trigger Property="IsFocused" Value="True"> 
       <Setter Property="FocusVisualStyle" 
         Value="{DynamicResource MyFocusVisualStyle}"/> 
      </Trigger> 
     </Style.Triggers> 
</Style> 

<Style x:Key="MyFocusVisualStyle"> 
     <Setter Property="Control.Template"> 
      <Setter.Value> 
       <ControlTemplate> 
        <Rectangle Stroke="Black" 
           StrokeDashArray="2 3" 
           Fill="Transparent" 
           StrokeDashCap="Round" 
           RadiusX="3" 
           RadiusY="3"/> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
</Style> 

C#

private void Contact_Select(object send, MouseButtonEventArgs e) 
    { 
     StackPanel sender = (StackPanel)send; 
     sender.Focus(); 
    } 

    private void StackPanel_GotFocus(object sender, RoutedEventArgs e) 
    { 
     StackPanel s = (StackPanel)sender; 
     s.Background = Brushes.Red; 
    } 

    private void StackPanel_LostFocus(object sender, RoutedEventArgs e) 
    { 
     StackPanel s = (StackPanel)sender; 
     s.Background = Brushes.Transparent; 
    } 

回答

1

我看到在執行兩個問題。首先its hard to capture mouse-events in a StackPanel with transparent background。其次,FocusVisualStyle only works when the last input is from the keyboard

要實現類似的視覺效果 - 您可以使用裝飾者來實現焦點風格。例如 - 你可以定義一個裝飾器是這樣的:

public class FocusAdorner : Adorner 
{ 
    // Be sure to call the base class constructor. 
    public FocusAdorner(UIElement adornedElement) 
     : base(adornedElement) 
    { 
     IsHitTestVisible = false; 
    } 

    // A common way to implement an adorner's rendering behavior is to override the OnRender 
    // method, which is called by the layout system as part of a rendering pass. 
    protected override void OnRender(DrawingContext drawingContext) 
    { 
     var drawRect = LayoutInformation.GetLayoutSlot((FrameworkElement)this.AdornedElement); 
     drawRect = new Rect(1, 1, drawRect.Width - 2, drawRect.Height - 2); 


     // Some arbitrary drawing implements. 
     SolidColorBrush renderBrush = new SolidColorBrush(Colors.Transparent); 
     Pen renderPen = new Pen(new SolidColorBrush(Colors.Black), 2); 
     renderPen.DashStyle = new DashStyle(new double[] { 2, 3 }, 0); 

     drawingContext.DrawRoundedRectangle(renderBrush, renderPen, drawRect, 3, 3); 
    } 
} 

用法示例 - XAML

<Window.Resources> 
    <!-- The "cell" I'm trying to acheive a dashed border around --> 

    <Style x:Key="ContactFocusStyle" TargetType="StackPanel"> 
     <Setter Property="Background" Value="White" /> 
     <Setter Property="FocusVisualStyle" Value="{x:Null}" /> 
     <Style.Triggers> 
      <Trigger Property="IsFocused" Value="True"> 
       <Setter Property="Background" Value="Red" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</Window.Resources> 
<Grid Margin="15"> 
    <Grid.RowDefinitions> 
     <RowDefinition /> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition /> 
     <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 
    <StackPanel 
     Grid.Row="0" 
     Grid.Column="0" 
     Focusable="True" 
     GotFocus="Got_Focus" 
     LostFocus="Lost_Focus" 
     PreviewMouseDown="Contact_Select" 
     Style="{DynamicResource ContactFocusStyle}"> 
     <!-- other children in here --> 
    </StackPanel> 
    <StackPanel 
     Grid.Row="0" 
     Grid.Column="1" 
     Focusable="True" 
     GotFocus="Got_Focus" 
     LostFocus="Lost_Focus" 
     PreviewMouseDown="Contact_Select" 
     Style="{DynamicResource ContactFocusStyle}"> 
     <!-- other children in here --> 
    </StackPanel> 
    <StackPanel 
     Grid.Row="1" 
     Grid.Column="0" 
     Focusable="True" 
     GotFocus="Got_Focus" 
     LostFocus="Lost_Focus" 
     PreviewMouseDown="Contact_Select" 
     Style="{DynamicResource ContactFocusStyle}"> 

     <!-- other children in here --> 
    </StackPanel> 
    <StackPanel 
     Grid.Row="1" 
     Grid.Column="1" 
     Focusable="True" 
     GotFocus="Got_Focus" 
     LostFocus="Lost_Focus" 
     PreviewMouseDown="Contact_Select" 
     Style="{DynamicResource ContactFocusStyle}"> 

     <!-- other children in here --> 
    </StackPanel> 
</Grid> 

和代碼隱藏

private void Contact_Select(object send, MouseButtonEventArgs e) 
{ 
    var sender = (StackPanel)send; 
    Keyboard.Focus(sender); 
} 

private void Got_Focus(object send, RoutedEventArgs e) 
{ 
    var sender = (StackPanel)send; 
    AdornerLayer.GetAdornerLayer(sender).Add(new FocusAdorner(sender)); 
} 

private void Lost_Focus(object send, RoutedEventArgs e) 
{ 
    var sender = (StackPanel)send; 
    var layer = AdornerLayer.GetAdornerLayer(sender); 
    foreach (var adorner in layer.GetAdorners(sender)) 
     layer.Remove(adorner); 
} 

** **輸出

enter image description here

+0

謝謝!這是一個很好的答案! –