none
用户控件可以用做UI模板嘛? RRS feed

  • 问题

  • 问题是这样的,我有N个窗口。它们的布局几乎相同。只有少量内容是不同的,如:显示的textbox或checkbox。我的打算是把这些相同的部分做成一个用户控件,然后新建窗口时,托入这个控件做为窗口操作的底层部分,而新窗口中只需要添加那些不同的内容就好了。

    但实际上,我把用户控件托入后会占满整个窗口的客户区,如果有其它的控件则不可见。

    刚才试了下,使用窗口来作模板,结果不行

    Severity	Code	Description	Project	File	Line	Suppression State
    Error		'WpfApp1.Uctrls.WindowBase' cannot be the root of a XAML file because it was defined using XAML. Line 1 Position 20.	WpfApp1	D:\Works\WpfApp1\WpfApp1\Window1.xaml	1	

    然后,我又想到用ControlTemplate,然后试了下,UI可见,模板中的textbox可以输入。button可以显示。

    但,我有几样不确定

    1。 如何将其它控件放到模板中的不同位置

    2.模板中的label如何赋值

    3.如何取得textbox的输入

    4。模板中的button的事件怎么挂载。

    我的字典内容如下

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:uctrls="clr-namespace:WpfApp1.Uctrls">
    
        <ImageSource x:Key="BtnCloseNormal">../images/others/popup_btn_reduction_normal.png</ImageSource>
        <ImageSource x:Key="BtnCloseMouseOver">../images/others/popup_btn_reduction_mouseover.png</ImageSource>
        <ImageSource x:Key="BtnClosePressed">../images/others/popup_btn_reduction_selected.png</ImageSource>
        
        
        <Style x:Key="StatedButtonStyle" TargetType="{x:Type uctrls:StatedButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type uctrls:StatedButton}" >
                        <Grid>
                            <Border>
                                <Image x:Name ="btnImg" Source="{Binding NormalBackground ,RelativeSource={RelativeSource TemplatedParent}}" Stretch="Fill"/>
                            </Border>
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="btnImg" Property="Source"  Value="{Binding MouseOverBackground ,RelativeSource={RelativeSource TemplatedParent}}"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="btnImg" Property="Source"  Value="{Binding PressedBackground ,RelativeSource={RelativeSource TemplatedParent}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        
        
        <Style x:Key="WindowBaseStyle" TargetType="{x:Type Window}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Window}">
                        <Grid Background="{x:Null}">
                            <Border CornerRadius="10" Background="White">
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="40"/>
                                        <RowDefinition Height="10"/>
                                        <RowDefinition/>
                                        <RowDefinition Height="30"/>
                                        <RowDefinition Height="10"/>
                                        <RowDefinition Height="20"/>
                                    </Grid.RowDefinitions>
                                    <Grid Grid.Row="0">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition/>
                                            <ColumnDefinition/>
                                            <ColumnDefinition Width="40"/>
                                            <ColumnDefinition Width="40"/>
                                            <ColumnDefinition Width="60"/>
                                        </Grid.ColumnDefinitions>
                                        <Label x:Name="lblTitle" Grid.Column="0" Margin="20,6,0,0" FontSize="18" FontWeight="Bold">
                                            <ContentPresenter/>  <!--此处原来是 标题 -->
                                        </Label>
                                        <!--自定义的button-->
                                        <uctrls:StatedButton Grid.Column="2" Width="30" Height="30" Style="{StaticResource StatedButtonStyle}"
                                                            NormalBackground="{StaticResource BtnCloseNormal}"
                                                            MouseOverBackground="{DynamicResource BtnCloseMouseOver}"
                                                            PressedBackground="{StaticResource BtnClosePressed}"/>
                                        <uctrls:StatedButton Grid.Column="3" Width="30" Height="30" Style="{StaticResource StatedButtonStyle}"
                                                            NormalBackground="{StaticResource BtnCloseNormal}"
                                                            MouseOverBackground="{DynamicResource BtnCloseMouseOver}"
                                                            PressedBackground="{StaticResource BtnClosePressed}"/>
                                        <uctrls:StatedButton Grid.Column="4" Width="30" Height="30" Style="{StaticResource StatedButtonStyle}"
                                                            NormalBackground="{StaticResource BtnCloseNormal}"
                                                            MouseOverBackground="{DynamicResource BtnCloseMouseOver}"
                                                            PressedBackground="{StaticResource BtnClosePressed}"/>
                                    </Grid>
                                    <Separator Background="LightGray" Grid.Row="1" Height="2"></Separator>
                                    <Grid Grid.Row="2">
                                        <Grid.Resources>
                                            <Style x:Key="StyleLbl" TargetType="{x:Type Label}">
                                                <Setter Property="Foreground" Value="LightGray"></Setter>
                                                <Setter Property="FontSize" Value="16"></Setter>
                                                <Setter Property="HorizontalAlignment" Value="Right"></Setter>
                                                <Setter Property="VerticalAlignment" Value="Center"></Setter>
                                                <Setter Property="Height" Value="30"></Setter>
                                            </Style>
    
                                            <Style x:Key="StyleTxt" TargetType="{x:Type TextBox}">
                                                <Setter Property="Foreground" Value="LightGray"></Setter>
                                                <Setter Property="FontSize" Value="16"></Setter>
                                                <Setter Property="HorizontalAlignment" Value="Left"></Setter>
                                                <Setter Property="Width" Value="220"></Setter>
                                                <Setter Property="Height" Value="30"></Setter>
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="{x:Type TextBox}">
                                                            <Grid>
                                                                <Rectangle RadiusX="5" RadiusY="5" Fill="{TemplateBinding Background}" Stroke="LightGray"  StrokeThickness="1"/>
                                                                <ScrollViewer x:Name="PART_ContentHost"
                                                                              HorizontalScrollBarVisibility="Hidden"
                                                                              VerticalScrollBarVisibility="Hidden"
                                                                              Padding="{TemplateBinding Padding}"
                                                                              Focusable="false">
                                                                </ScrollViewer>
                                                            </Grid>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
    
                                        </Grid.Resources>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="20"/>
                                            <ColumnDefinition Width="1.5*"/>
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="30"/>
                                            <RowDefinition/>
                                            <RowDefinition/>
                                            <RowDefinition/>
                                            <RowDefinition Height="30"/>
                                        </Grid.RowDefinitions>
    
                                        <Label Grid.Column="0" Grid.Row="1" Style="{StaticResource StyleLbl}">
                                            <ContentPresenter/> <!--测试用的label文字显示-->
                                        </Label>
                                        <Label Grid.Column="0" Grid.Row="2" Style="{StaticResource StyleLbl}">
                                            <ContentPresenter/>
                                        </Label>
                                        <Label Grid.Column="0" Grid.Row="3" Style="{StaticResource StyleLbl}">
                                            <ContentPresenter/>
                                        </Label>
                                            <!--输入文本框-->
                                        <TextBox x:Name="txtIp" Grid.Column="2" Grid.Row="1" Style="{StaticResource StyleTxt}"></TextBox>
                                        <TextBox x:Name="txtUser" Grid.Column="2" Grid.Row="2" Style="{StaticResource StyleTxt}"></TextBox>
                                        <TextBox x:Name="txtPsw" Grid.Column="2" Grid.Row="3" Style="{StaticResource StyleTxt}"></TextBox>
                                    </Grid>
                                    <Button Grid.Row="3" Width="300" BorderBrush="{x:Null}" Foreground="White" FontSize="16" Margin="0,0,0,-1.8">
                                        <Button.Template>
                                            <ControlTemplate TargetType="Button" >
                                                <Grid>
                                                    <Border>
                                                        <Image x:Name ="btnImg" Source="../images/others/popup_btn3_connnect_normal.png" Stretch="Fill"/>
                                                    </Border>
                                                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
                                                </Grid>
    
                                                <ControlTemplate.Triggers>
                                                    <Trigger Property="IsMouseOver" Value="True">
                                                        <Setter TargetName="btnImg" Property="Source"  Value="../images/others/popup_btn3_connnect_mouseover.png"/>
                                                    </Trigger>
                                                    <Trigger Property="IsMouseCaptured" Value="True">
                                                        <Setter TargetName="btnImg" Property="Source"  Value="../images/others/popup_btn3_connnect_selected.png"/>
                                                    </Trigger>
                                                </ControlTemplate.Triggers>
                                            </ControlTemplate>
                                        </Button.Template>
                                        <ContentPresenter/> <!--button的文字说明-->
                                    </Button>
                                    <Image Grid.Row="4" Source="../images/others/popup_btn3_connnect_downshadow.png" ></Image>
                                </Grid>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        
        
        
    </ResourceDictionary>

    求解。模板中的 注释 部分是需要解决的问题所在。
    • 已编辑 jinli.zh 2017年11月11日 15:33 再次补充
    2017年11月11日 15:29

答案

  • 如我上次的做法就可以将业务控件放到窗体上。然后创建一个window的子类,在其

    onApplyTemplate方法里可以通过getTemplateChild得到模板控件。

    新创建的window子类用做窗口基类(假设为 windowbase)。再次创建窗口时,把基类改成windowbase,并将xaml的window也可改windowbase 即可。

    • 已标记为答案 jinli.zh 2017年11月14日 11:43
    2017年11月14日 11:43

全部回复


  • Hi jinli.zh,

    我建议你创建用户控件,来显示你一样的信息。

    >>但实际上,我把用户控件托入后会占满整个窗口的客户区,如果有其它的控件则不可见

    这个你可以通过Grid一些布局控件,来布局你不同的控件。而不是让用户控件占满整个form。

    比如下面的代码:

    Mainform:

     <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0">...</TextBlock>
            <DockPanel x:Name="ContentArea" Grid.Row="1" />
        </Grid>
    
          private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                UserControl1 uc = new UserControl1();
                this.ContentArea.Children.Add(uc);
    
            }

    Usercontrol:

    <UserControl x:Class="Wpf_temp.UserControl1"
                 d:DesignHeight="300" d:DesignWidth="300" HorizontalAlignment="Stretch"
    	VerticalAlignment="Stretch"
    	HorizontalContentAlignment="Stretch"
    	VerticalContentAlignment="Stretch"
        Height="auto"
        Width="auto">
        <Grid>
            <Button Content="Button" HorizontalAlignment="Left" Margin="198,170,0,0" VerticalAlignment="Top" Width="75"/>
            <ListBox HorizontalAlignment="Left" Height="100" Margin="27,28,0,0" VerticalAlignment="Top" Width="100"/>
            <RadioButton Content="RadioButton" HorizontalAlignment="Left" Margin="169,53,0,0" VerticalAlignment="Top"/>
            <Label Content="Label" HorizontalAlignment="Left" Margin="81,158,0,0" VerticalAlignment="Top"/>
        </Grid>
    </UserControl>


    >>然后,我又想到用ControlTemplate,然后试了下,UI可见,模板中的textbox可以输入。button可以显示。

    ControlTemplate 主要是为控件定义一个模板,指定可视结构和行为方面 Control ,可以跨多个控件实例共享。我并不觉得适用你的情况。

    ControlTemplate 类:
    https://msdn.microsoft.com/zh-cn/library/system.windows.controls.controltemplate(v=vs.110).aspx


    Best Regards,

    Yohann Lu



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年11月13日 8:13
    版主
  • 多谢回复。事实上,使用usercontrol并不是很好。因为我的code屏示的是一个窗口部分的基本外观。至于业务部分则需要后续添加。

    我今天试验了controltemplate是可以实现添加自己需要的业务控件的。做法是像窗口中的grid一样,使用

    <AdornerDecorator>

    <contentpresenter/>

    </AdornerDecorator>

    来允许添加其它控件。

    其它仍在测试中

    2017年11月13日 13:55

  • Hi  jinli.zh,

    如果你有新的进展可以和大家分享。

    如果有新的问题,你可以在对应的论坛开启一个新的线程(请不要在一个问题中问好几个问题)。

    Best Regards,

    Yohann Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    2017年11月14日 2:36
    版主
  • 如我上次的做法就可以将业务控件放到窗体上。然后创建一个window的子类,在其

    onApplyTemplate方法里可以通过getTemplateChild得到模板控件。

    新创建的window子类用做窗口基类(假设为 windowbase)。再次创建窗口时,把基类改成windowbase,并将xaml的window也可改windowbase 即可。

    • 已标记为答案 jinli.zh 2017年11月14日 11:43
    2017年11月14日 11:43