自动转换,c#

本文关键字:转换 | 更新日期: 2023-09-27 18:11:07

请分析这段代码。我创造了这样的想法:我们可以将标签和控件合并到一个通用控件中。我是这样实现的:

//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;

自动转换,c#

如果你正在使用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 }
};

我想Jon已经给你答案了。但是,您可能想要考虑使用基于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,并添加了一个"Label"依赖属性。

现在打开主题/通用。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将其包装起来,这样我们就可以将TextBlock绑定到Label属性。

你现在可能已经注意到,这些都不能真正解决你想要解决的"问题"。我只是指出一种更"Silverlight-esq"的方法来创建复合控件,它更灵活。

对于你的具体问题,我会说这实际上不是问题,在Jon的最后一个示例中,他展示了如何构造代码以避免重复。使用上面的控件,代码看起来像:-

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

OR在Xaml:-

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

正如vcsjones向Jon指出的那样,使用泛型类并不是Silverlight非常友好的方法,我会避免使用泛型类。