2012-03-23 68 views
3

我有一個WPF表單,它由兩列網格組成。在WPF中訪問用戶控件

左欄是控件標籤,右欄是我的控件。

這些控件都是UserControls。在最簡單的情況下,這些控件中的一些只是簡單地包裝現有的WPF控件(如文本框),以便它們都實現一個通用接口。

當產生形式,我有這樣的代碼設定的標籤相關聯的控制,其中newControl是所創建的用戶控件和ctl.Caption簡單地返回所需標籤文本:

Label newLabel = new Label(); 
newLabel.Content = ctl.Caption + ":"; 
newLabel.Target = newControl; 

的一個問題是否設定目標實際上不工作。如果在標題中有下劃線,則助記鍵不會將焦點設置爲包裝控件。對此的一種解決方法可能是手動將焦點設置爲UserControl代碼中的包裝控件 - 但是...

最大的問題是可訪問性。屏幕閱讀器(如JAWS和Windows內置講述人)在控件獲得焦點時不會閱讀控件標題。

我看過這個:http://msdn.microsoft.com/en-us/library/windows/desktop/gg712258.aspx - 它提供了很多細節,但沒有有用的例子。它有很多關於定製控件的東西,這對於一個簡單的用戶控件肯定是矯枉過正?

那麼,我怎樣才能將我的標籤正確地附加到我的UserControl?

您可以在http://quest.codeplex.com/SourceControl/changeset/view/676933506953瀏覽整個項目的代碼 - 特定代碼位於EditorControls項目中,UserControls在ElementEditor.xaml.cs中實例化。

+0

我會使用Decorator模式,如它將允許你'包裝'XAML中的控件(即不必創建自定義控件)。我將在下班後的今天晚些時候發佈一個例子。 – Dennis 2012-03-26 13:06:48

回答

0

hmmm我試圖在一個小測試項目上重現你的問題,但對我來說它的工作原理...所以我想你必須提供更多關於你的userControls如何構建的細節。下面是我的什麼作品:

我創建了一個空項目(只是應用程序和窗口文件,像往常一樣),併成立了一個網格,兩列在我的窗口:

<Window x:Class="Test.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" 
     Name="Window" 
     SizeToContent="WidthAndHeight"> 

    <Grid Name="MyGrid"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="100" /> 
      <ColumnDefinition Width="100"/> 
     </Grid.ColumnDefinitions> 
    </Grid> 

</Window> 

然後創建一個用戶控件它擴展了WPF TextBox類:

<TextBox x:Class="Test.MyTextBox" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 

</TextBox> 

和:使用System.Windows

; using System.Windows.Controls;

namespace Test 
{ 
    public partial class MyTextBox : TextBox 
    { 
     public static readonly DependencyProperty CaptionProperty = 
      DependencyProperty.Register("Caption", typeof(string), typeof(MyTextBox), new UIPropertyMetadata("")); 
     public string Caption 
     { 
      get { return (string)GetValue(CaptionProperty); } 
      set { SetValue(CaptionProperty, value); } 
     } 

     public MyTextBox() 
     { 
      InitializeComponent(); 
     } 
    } 
} 

它基本上是一個帶有「Caption」dp的文本框。在後面我窗口的代碼

現在:

public MainWindow() 
{ 
    InitializeComponent(); 

    MyTextBox tb = new MyTextBox { Caption = "_Foo", Width = 100 }; 
    Label lb = new Label { Content = tb.Caption + ":", Target = tb }; 

    MyGrid.Children.Add(lb); 
    MyGrid.Children.Add(tb); 

    Grid.SetColumn(lb, 0); 
    Grid.SetColumn(tb, 1); 
} 

以及與此,我得到重點TB當我按ALT + F(我甚至可以看到_下的「富」的F-在標籤時只需按下ALT)

所以我想您的問題與您的用戶控件做自己和他們是如何構建的(什麼模板實例)

編輯:

如果您的控件未擴展現有控件,而是包含 WPF控件,則問題可能出在Focus方法上。當控件本身獲得焦點時,應該添加一個Focus()方法,該方法將焦點設置在控件的右側。

代碼(包含您想獲得例如焦點的文本框一個用戶控件):

<TextBox x:Class="Test.MyTextBox" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 

    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
      <ColumnDefinition /> 
     </Grid.ColumnDefinitions> 

     <Button Content="foo" Grid.Column="0" /> 
     <TextBox Name="TextBoxPart" Grid.Column="1" /> 
    </Grid> 

</TextBox> 

代碼背後

public partial class MyTextBox : TextBox 
{ 
    public static readonly DependencyProperty CaptionProperty = 
     DependencyProperty.Register("Caption", typeof(string), typeof(MyTextBox), new UIPropertyMetadata("")); 
    public string Caption 
    { 
     get { return (string)GetValue(CaptionProperty); } 
     set { SetValue(CaptionProperty, value); } 
    } 

    public MyTextBox() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnGotFocus(RoutedEventArgs e) 
    { 
     TextBoxPart.Focus(); 
    } 
} 

編輯2: 我有一個問題,一旦,將焦點轉移到dataGridCell中的子控件,這裏是我在模板中所做的:

<ControlTemplate.Triggers> 
    <Trigger Property="IsFocused" Value="True"> 
      <Setter TargetName="TextBoxPart" Property="FocusManager.FocusedElement" Value="{Binding ElementName=TextBoxPart}" /> 
    </Trigger> 
</ControlTemplate.Triggers> 

你可以嘗試添加這個到你的模板。這應該轉移你的注意力。

爲輔助功能,我不認爲這會有所幫助,但我不明白你想要什麼實現的任何方式: -/

+0

在我的情況下,我不擴展任何現有的控件,只是包裝它們。因此,也許我有例如一些MyCustomTextBoxControl,它可能包含*一個文本框,但不會從它派生(也許是因爲它也有一個按鈕或旁邊的東西) – 2012-03-28 16:18:47

+0

那是我在想什麼,然後看我的編輯 – David 2012-03-28 17:47:00

+0

感謝大衛,我剛剛給出了一個結論,但似乎沒有任何效果。即使如此,可訪問性仍然被破壞 - 使用Narrator或JAWS時,專注於文本框仍然不會讀出標籤標題。 – 2012-03-28 19:14:41

1

你newControl是類型控制的,它不允許你添加額外的內容。 如果你想添加一些內容,你需要使用一個支持它的類,比如ContentControl或者Panel(對於多個孩子),你可以實現你自己的控件來實現IAddChild接口。

你一個簡單的解決問題可能是:

<UserControl x:Class="UIMocks.MyCustomControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <StackPanel x:Name="content"/> 
</UserControl> 

代碼隱藏

[ContentProperty("Children")] 
public partial class MyCustomControl : UserControl 
{ 
    public MyCustomControl() 
    { 
     InitializeComponent(); 
    } 

    public UIElementCollection Children { get { return content.Children; } } 
} 

,然後你可以使用

MyCustomControl newControl = InitialiseEditorControl(ctl); 
... 
Label newLabel = new Label(); 
newLabel.Content = ctl.Caption + ":"; 
newControl.Children.Add(newLabel); 
+0

AddChild在ContentControl上受到保護,因此無法在我的AddControlToGrid函數中訪問它。並且UserControl不能轉換爲Panel。此外,從文檔中可以看出,IAddChild在.net 4中已棄用。 – 2012-04-02 13:56:28

+0

您是對的IAddChild現在已過時,它已被替換爲e ContentProperty屬性。感謝您的支持。 我並沒有試圖說他應該將他的用戶控件投射到一個Panel上,只是說他可以使用一個具有像Panel這樣的內容的控件(它是抽象的,不能直接使用) – 2012-04-02 15:00:22