2011-10-13 57 views
0

請分析此代碼..我創建了一個想法,我們可以在一個通用控件中加入標籤和控件。我實現了這種方式:自動轉換,C#

//my class 
public partial class WrappingControl : UserControl 
{ 
    public string MyLabel { get { return lb.Text; } set { lb.Text = value; } } 

    public UIElement MyControl { get { return uc.Content; } set { uc.Content = value; } } 

    public T CastControl<T>() 
    { 
     return (T)Convert.ChangeType(MyControl, typeof(T), null); 
    } 
} 

//silverlight class 
public partial class WrappingControl : UserControl 
{ 
    TextBlock lb; 
    UserControl uc; 
} 

,我可以使用,像這樣的東西:

var wc =new WrappingControl(); 
     wc.MyLabel = "ID:"; 
     wc.MyControl = new TextBox(); 
     wc.CastControl<TextBox>().Text="123"; 


     var wc2 = new WrappingControl(); 
     wc2.MyLabel = "Is Ok?:"; 
     wc2.MyControl = new CheckBox(); 
     wc2.CastControl<CheckBox>().IsChecked = true; 

唯一的缺點是,我不得不重複我想要的控制類型,但我想知道如果有一種方法(可能是通過反射)檢測控件類型並返回這種類型的對象並獲得智能感知。如:

wc.ActualControl.Text = "123"; 
wc2.ActualControl.IsChecked = true; 

回答

0

我覺得喬恩的給你答案。但是,您可能需要考慮使用基於ContentControl而不是UserControl的模板控制。這裏有一個10的啓動器。

將一個新的Silverlight模板控制項目添加到您的項目中調用其「LabeledControl」。

修改cs文件創建,以便它看起來像這樣: -

public class LabeledControl : ContentControl 
{ 
    public LabeledControl() 
    { 
     this.DefaultStyleKey = typeof(LabeledControl); 
    } 

    #region public string Label 
    public string Label 
    { 
     get { return GetValue(LabelProperty) as string; } 
     set { SetValue(LabelProperty, value); } 
    } 


    public static readonly DependencyProperty LabelProperty = 
     DependencyProperty.Register(
      "Label", 
      typeof(string), 
      typeof(LabeledControl), 
      new PropertyMetadata(null)); 
    #endregion public string Label 
} 

你會注意到所有我們所做的是改變類被繼承到ContentControl並添加了一個「標籤」依賴屬性。

現在打開Themes/Generic.xaml文件並找到該控件的默認樣式。與此替換它: -

<Style TargetType="local:LabeledControl"> 
    <Setter Property="Foreground" Value="#FF000000"/> 
    <Setter Property="HorizontalContentAlignment" Value="Left"/> 
    <Setter Property="VerticalContentAlignment" Value="Top"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="local:LabeledControl"> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto" /> 
         <RowDefinition Height="*" /> 
        </Grid.RowDefinitions> 
        <TextBlock Text="{TemplateBinding Label}" /> 
        <ContentPresenter 
          Content="{TemplateBinding Content}" 
          ContentTemplate="{TemplateBinding ContentTemplate}" 
          Cursor="{TemplateBinding Cursor}" 
          Margin="{TemplateBinding Padding}" 
          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
        </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

所有我們在這裏所做的是複製了原有的風格爲ContentControl包好了Grid,所以我們可以把我們綁定到Label財產TextBlock

您現在可能已經注意到,這些都沒有解決您想要解決的「問題」。我只是指出了創建複合控件的更多「Silverlight-esq」方法,它更加靈活。

對於您的具體問題,我會說它其實不是一個問題,在Jon的最後一個示例中,他展示瞭如何構建代碼以避免重複。通過上述控制代碼將如下所示: -

var lc = new LabeledControl 
{ 
    Label = "Check this:", 
    Content = new CheckBox {IsChecked = True} 

}; 

或在XAML: -

<local:LabeledControl Label="Check this:"> 
    <CheckBox IsChecked="True" /> 
</local> 

由於vcsjones使用泛型類使用指出喬恩並不是很Silverlight的友好的方式,我會避免這一點。

4

如果您使用的是C#4和.NET 4,則可以使用動態鍵入。更改屬性類型dynamic和你離開:

wc.WrappedControl = new CheckBox(); 
wc.WrappedControl.IsChecked = true; 

請注意,您無法檢測到執行時間類型的控件,並期望有對編譯時的效果類型。

您是否考慮過使用泛型?

public partial class WrappingControl<T> : UserControl where T : UIElement 
{ 
    public T WrappedControl { get; set; } // Add appropriate logic 
} 

var wc2 = new WrappingControl<CheckBox>(); 
wc2.WrappedControl = new CheckBox(); 
wc2.WrappedControl.IsChecked = true; 

如果T一個new()約束,WrappingControl甚至可以創建嵌套控制。

另一種方法是使用一個對象初始化,以避免提及經常控制:

var wc = new WrappedControl 
{ 
    MyLabel = "Test", 
    MyControl = new CheckBox { IsChecked = true } 
}; 
+0

如果在XAML標記中使用XAML,則Silverlight的XAML無法處理控件中的泛型。當然,XAML 2009支持泛型 - 但只是作爲寬鬆的文檔。如果這只是代碼,那麼泛型肯定會起作用。 – vcsjones

+0

@vcsjones:看起來這是從XAML以外的代碼隱藏中使用,但您的觀點已被採納。 –

+0

使用動態的第一個想法將解決問題,另一個想法並不是非常有用,因爲XAML不允許泛型,最後一個並不能解決問題,即如何在讀/寫控件的屬性之後它是由XAML創建的。 – Jaider