微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Silverlight学习点滴之二——为RadioButton换上新衣

WPF/Silverlight有个叫做模板的东西,可以为控件创建自定义的样式。

比如,有一组RadioButton(俗称“单选框”),在WrapPanel中自由排列,如下图的样子: 

\

 

打算山寨一下淘宝网的界面,做成这样:

\

 

开始折腾···

创建UserControl

自定义用户控件,也就是图中“数据生成时间”以及下方的RadioButton。
取名FilterBox,布局很简单,Grid上方是一个标题,下方WrapPanel:

<UserControl>
    <Grid x:Name="LayoutRoot"Background="Transparent">
        <Grid.RowDeFinitions>
            <RowDeFinition Height="35*"/>
            <RowDeFinition Height="91*"/>
        </Grid.RowDeFinitions>
        <toolkit:WrapPanel Name="wrap"Grid.Row="1"Margin="0"HorizontalAlignment="Stretch"VerticalAlignment="Stretch">
        </toolkit:WrapPanel>
        <TextBlock Name="title"Margin="0"Height="Auto"Text="标题"HorizontalAlignment="Center"VerticalAlignment="Center">
        </TextBlock>
    </Grid>
</UserControl>

WrapPanel能够让他的Children横向排列,一行排满之后,会自动换行,用在这里是在适合不过了。

创建样式

选中的RadioButton样式可以看成一个粗边框+右下角的一个三角形;未选中的则用一个细的边框表示。

在UserControl下面增加Resources属性

<Control.Resources>
    <!--控件模板,Key为必需,并且设定目标类型为RadioButton-->
    <ControlTemplate x:Key="Checked"targettype="RadioButton">
        <Grid>
            <!--选中状态:粗边框-->
            <Border Margin="1"BorderBrush="Blue"BorderThickness="2"Padding="4,1,4,0">
                <!--内部的文字内容绑定了RadioButton的Content属性-->
                <TextBlock Text="{TemplateBinding ContentControl.Content}"/>
            </Border>
            <!--三角形用polygon表示-->
            <polygon Margin="1"Points="10,1 10,10 0,10"HorizontalAlignment="Right"VerticalAlignment="Bottom">
                <polygon.Fill>
                    <SolidColorBrush Color="Blue"/>
                </polygon.Fill>
            </polygon>
        </Grid>
    </ControlTemplate>
    <ControlTemplate x:Key="UnChecked"targettype="RadioButton">
        <Grid>
            <!--未选中状态:细边框-->
            <Border Margin="2"BorderBrush="Gray"BorderThickness="1"Padding="4,0">
                <TextBlock Text="{TemplateBinding ContentControl.Content}"/>
            </Border>
        </Grid>
    </ControlTemplate>
</Control.Resources>

在WrapPanel中添加两个RadioButton,分别设定两种不同样式,转到设计界面查看效果

<toolkit:WrapPanel Name="wrap"Grid.Row="1"HorizontalAlignment="Stretch"Margin="0"VerticalAlignment="Stretch">
    <RadioButton Content="Checked"Template="{StaticResource Checked}"/>
    <RadioButton Content="UnChecked"Template="{StaticResource UnChecked}"/>
</toolkit:WrapPanel>

\

实现

在实际使用中,需要动态添加RadioButton。
在WPF中,可以使用Setter样式,对控件某个属性的不同状态设定不同的样式(即选择不同的模板);而在Silverlight中,Setter是不被支持的,所以只能编写C#代码实现:

publicpartialclassFilterBox : UserControl
{
    publicstringTitle { get{ returntitle.Text; } }

    publicstringSelectedValue { get; privateset; }

    publiceventRoutedEventHandler CheckChanged;

    publicFilterBox()
    {
        InitializeComponent();
    }

    publicFilterBox(stringname,IEnumerable<string> values)
    {
        InitializeComponent();
        this.title.Text = name;

        // 添加“全部”选择项
        var c = CreateItem("全部");
        c.IsChecked = true;
        this.wrap.Children.Add(c);
        this.SelectedValue = c.Content asstring;

        // 添加一般选择项
        foreach(var i invalues)
            this.wrap.Children.Add(CreateItem(i));
    }

    privatevoidWhenCheckChanged(objectsender,RoutedEventArgs e)
    {
        var c = sender asRadioButton;
        var isChecked = c.IsChecked ?? false;
        // 依据IsChecked属性值选择模板
        c.Template = Resources[isChecked ? "Checked": "UnChecked"] asControlTemplate;

        if(isChecked)
        {
            this.SelectedValue = c.Content asstring;
            // 触发CheckChanged事件,以便外部代码访问
            if(CheckChanged != null)
                CheckChanged(this,null);
        }
    }

    // 创建新的单选项
    privateradioButton CreateItem(stringitem)
    {
        var radio = newRadioButton();
        radio.Content = item;
        // 设定缺省的UnChecked模板
        radio.Template = this.Resources["UnChecked"] asControlTemplate;
        // 订阅事件
        radio.Checked += WhenCheckChanged;
        radio.Unchecked += WhenCheckChanged;
        returnradio;
    }
}

接着创建一个ChildWindow用户控件,取名ChildWindowX。在Loaded事件响应方法中创建FilterBox

privatevoidChildWindow_Loaded(objectsender,RoutedEventArgs e)
{
    LayoutRoot.Children.Add(newFilterBox("数据生成时间",
        newstring[] { "更早","2006","2007","2008","2009","2010","2011"}));
}

\

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐