WPF,这个控件的宽度为什么没有效果?

d454ew32 2014-12-02 11:24:32
一个UserControl1:

<UserControl x:Class="WPF3.UserControl1"
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 Background="#FFC11D1D"/>
</UserControl>


public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.Height = 100;
this.Width = 100;
}
}

一个CustomControl1,控件模板中使用了UserControl1 ,并在XAML中将UserControl1 的Width设为2:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF3">
<Style TargetType="{x:Type local:CustomControl1}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl1}">
<Border>
<local:UserControl1 Width="2"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

主窗体:


<Window x:Class="WPF3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF3"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:CustomControl1/>
</Grid>
</Window>


最终的结果,为什么UserControl 的宽度不是2呢?在UserControl 的构造函数中,我设置断点试过,在设置Width为100之前,Width的值是为NaN的,那XAML中的那句Width="2",为什么就没有执行呢?
...全文
735 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
d454ew32 2014-12-05
  • 打赏
  • 举报
回复
引用 14 楼 Forty2 的回复:
问你自己如下问题: 1、12楼中的UserControl2和UserControl1是通过模板创建出来的吗?你看到类似Template的语句了吗? 2、13楼的<Control Style="{StaticResource aa}"/>,是否通过模板来自定义Control?Style里面的UserControl1是不是ControlTemplate的一部分?
不是通过模板创建的。不过,我查了下9楼的FrameworkElementFactory类:MSDN 这是一个弃用的类呢。 我在MSDN、网上搜索了一下阁下所说的用“工厂”创建控件,以及此时的优先级。都没有这方面的资料。我想学得更多一点、更扎实点这方面的知识块。
Forty2 2014-12-05
  • 打赏
  • 举报
回复
问你自己如下问题: 1、12楼中的UserControl2和UserControl1是通过模板创建出来的吗?你看到类似Template的语句了吗? 2、13楼的<Control Style="{StaticResource aa}"/>,是否通过模板来自定义Control?Style里面的UserControl1是不是ControlTemplate的一部分?
d454ew32 2014-12-05
  • 打赏
  • 举报
回复
同样,就算是用个样式,也没有效果:

<Window x:Class="WPF3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF3"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="aa" TargetType="Control">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border>
<local:UserControl1 Width="2"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Control Style="{StaticResource aa}"/>
<local:UserControl2/>
</StackPanel>
</Grid>
</Window>

d454ew32 2014-12-05
  • 打赏
  • 举报
回复
引用 9 楼 Forty2 的回复:
首先要明确的概念是:Template不是具体的控件,而只是一个模板(用同一个模板可以生产多个具体的控件)。
因此对模板的属性设置,并没有直接设置到具体的控件上。。

还是不太理解。我有新建了一个UserControl2:

<UserControl x:Class="WPF3.UserControl2"
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"
xmlns:local="clr-namespace:WPF3"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<local:UserControl1 Width="2"/>
</Grid>
</UserControl>

同样使用了UserControl1 ,并把Width设为2,但是却是有效果的。

<Window x:Class="WPF3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF3"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<local:CustomControl1/>
<local:UserControl2/>
</StackPanel>
</Grid>
</Window>

这又是为什么呢?
d454ew32 2014-12-05
  • 打赏
  • 举报
回复
不能结贴 ?
Forty2 2014-12-05
  • 打赏
  • 举报
回复
引用 15 楼 d454ew32 的回复:
...这是一个弃用的类呢。
之所以弃用,是因为它不能完成Xaml的所有功能。但是不妨碍我们用代码去理解xaml中模板的实现。 下面的例子给出三种模板(可以用鼠标点击来轮换): 1、没有模板 2、使用代码创建模板(用‘弃用’的FrameworkElementFactory) 3、使用载入Xmal的方式创建模板(所谓‘正确’的创建方式) 例子要说明的是: 1、Xmal的Template如果用代码创建,如何表达 2、在代码表达中,可以清楚地看到,模板中的‘元素’实际上都是‘元素工厂’(Xaml模板中看不出来)。 3、在代码表达中,属性的设置,实际上是先设置到‘‘元素工厂’上。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <StackPanel>
        <Control Name="myControl" />
    </StackPanel>
</Window>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.Title = "鼠标点击,显示几种模板的效果[无,代码模板,xaml模板]";
            ControlTemplate[] templates = { null, CreateTemplateCode(), CreateTemplateXaml() };
            int i = 0;
            this.MouseDown += delegate { myControl.Template = templates[++i % templates.Length];};
        }

        ControlTemplate CreateTemplateCode()
        {
            var borderFactory = new FrameworkElementFactory(typeof(Border));  // <Border>
            var userControl1Factory = new FrameworkElementFactory(typeof(UserControl1)); // <local:UserControl1
            borderFactory.SetValue(Border.BackgroundProperty, Brushes.Yellow); // 代码方式额外改变Border的背景,以便区别
            userControl1Factory.SetValue(UserControl1.WidthProperty, 2.0); // Width="2" />
            borderFactory.AppendChild(userControl1Factory);

            ControlTemplate controlTemplate = new ControlTemplate(typeof(Control));
            controlTemplate.VisualTree = borderFactory;

            return controlTemplate;
        }

        ControlTemplate CreateTemplateXaml()
        {
            string xaml = string.Format(
                @"<ControlTemplate TargetType='Control' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>
                    <Border>
                        <local:UserControl1 Width='2' xmlns:local='clr-namespace:{0};assembly={1}'/>
                    </Border>
                </ControlTemplate>",
                typeof(UserControl1).Namespace,
                typeof(UserControl1).Assembly.GetName().Name);

            return (ControlTemplate)XamlReader.Parse(xaml);
        }
    }

    // 可以不需要另外的UserControl1.xaml
    public class UserControl1 : UserControl
    {
        public UserControl1()
        {
            this.Background = Brushes.Red;
            this.Height = 100;
            this.Width = 100;
        }
    }
}
Forty2 2014-12-04
  • 打赏
  • 举报
回复
首先要明确的概念是:Template不是具体的控件,而只是一个模板(用同一个模板可以生产多个具体的控件)。 因此对模板的属性设置,并没有直接设置到具体的控件上。 要解释这点,可以把你Xaml中有关Template的部分,换成代码实现:

FrameworkElementFactory borderFactory = new FrameworkElementFactory(typeof(Border));  // <Border>
FrameworkElementFactory userControl1Factory = new FrameworkElementFactory(typeof(UserControl1)); // <local:UserControl
userControl1Factory.SetValue(UserControl1.WidthProperty, 2.0); // Width="2" />
borderFactory.AppendChild(userControl1Factory);

ControlTemplate customControl1Template = new ControlTemplate(typeof(CustomControl1));
customControl1Template.VisualTree = borderFactory;
//...
可以看到,当你写<local:UserControl1 Width="2"/>的时候,属性并不是直接设置到UserControl1上的,而是设置到一个FrameworkElementFactory的工厂上。 当WPF运行中对控件施用模板时,工厂再 1、创建具体的控件实例 2、并把工厂中的模板属性值,应用到实例去。 这里说的应用模板属性,就会有优先级的考虑,很可能这种模板属性的优先级比‘本地值’低(在构造函数里直接设置的算本地值)。 这个可以解释为什么,在构造函数中设置的宽度高度(本地值),不会被模板中的数值覆盖。 相反,如果在StackPanel中直接实例化UserControl1,并设置宽度。那么该设置是‘本地值’,可以生效。
d454ew32 2014-12-04
  • 打赏
  • 举报
回复
能否搜集点更多的解释呢?
d454ew32 2014-12-03
  • 打赏
  • 举报
回复
引用 7 楼 wangweicai 的回复:
等于2的处理是在InitializeComponent()里执行了,之后又执行了this.Width = 100;所以等于2就不好使了。在调试构造函数时,里面的属性是在构造函数执行完了以后才起作用的,所以,在构造函数里设断点作用不大,你可以试试把this.Width = 100;去掉看看。
等于2的处理是在InitializeComponent()里执行了?等于2是在CustomControl1的样式中设置的啊,又不是在UserControl1的XAML中设置的。好吧,UserControl1的InitializeComponent方法加载的应该是UserControl1的XAML吧。 好吧,如果如你所说的话,看下面的代码:


<Window x:Class="WPF3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPF3"
        Title="MainWindow" Height="350" Width="525">
   <Grid>
        <StackPanel>
            <local:CustomControl1/>
            <local:UserControl1 Width="2"/>
        </StackPanel>
    </Grid>
</Window>
同样是在XMAL中设置UserControl1的Width为2,这个就有效,而在CustomControl1的XAML中设置UserControl1的Width为2就没有效果,这是为什么呢?
wangweicai 2014-12-03
  • 打赏
  • 举报
回复
等于2的处理是在InitializeComponent()里执行了,之后又执行了this.Width = 100;所以等于2就不好使了。在调试构造函数时,里面的属性是在构造函数执行完了以后才起作用的,所以,在构造函数里设断点作用不大,你可以试试把this.Width = 100;去掉看看。
d454ew32 2014-12-03
  • 打赏
  • 举报
回复
跪求高人..........
枫0子K 2014-12-02
  • 打赏
  • 举报
回复
我也是WPF的新手~ 我看你这代码的意思,不应该是在CustomControl的内容里面嵌入了一个宽度为2的UserControl吗??
d454ew32 2014-12-02
  • 打赏
  • 举报
回复
有人知道吗????????????
d454ew32 2014-12-02
  • 打赏
  • 举报
回复
引用 3 楼 ZuoQingYi 的回复:
WPF对依赖属性值的读取是有优先级控制的,由先到后依次是:


<Window x:Class="WPF3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPF3"
        Title="MainWindow" Height="350" Width="525">
   <Grid>
      <local:UserControl1 Width="2"/>
    </Grid>
</Window>
那为什么,在主窗体中设置的UserControl1的Width值又有效呢?
沐青衣 2014-12-02
  • 打赏
  • 举报
回复
WPF对依赖属性值的读取是有优先级控制的,由先到后依次是: (1)WPF属性系统强制值。 (2)由动画过程控制的值。 (3)本地变量值(存储在EffectiveValueEntry数组中)。 (4)由上级元素的Template设置的值。 (5)由隐式样式(Implicit Style)设置的值。 (6)由样式之触发器(Style Trigger)设置的值。 (7)由模板之触发器(Template Trigger)设置的值。 (8)由样式之设置器(Style Setter)设置的值。 (9)由默认样式(Default Style)设置的值,默认模式其实就是由主题(Theme)指定的模式。 (10)由上级元素继承而来的值。 (11)默认值,来源于依赖属性的元数据(metadata)。
d454ew32 2014-12-02
  • 打赏
  • 举报
回复
引用 1 楼 Yokeqi 的回复:
我也是WPF的新手~ 我看你这代码的意思,不应该是在CustomControl的内容里面嵌入了一个宽度为2的UserControl吗??
我就是这个意思啊,可是,为什么UserControl的宽度就不是2呢?
Microsoft WpfToolkit的更新和扩展: 1、将库版本升级到.NET 4.5,对命名控件进行了替换处理 2、实现了单数据Chart图的混合颜色显示,可通过修改资源字典调整和添加颜色 3、可控制各种Chart图形的数据值显 示 4、坐标轴文本可倾斜显示 5、添加了StepLine图和圆环图,圆环半径比例系数可设定. 6、Legend可位于区域四侧,对齐方式也可以设定,以及是否显示, 可控制Chart Title是否显示 7、柱状图缝隙间隔可调整 8、全方面的加入了各种加载动画效果,动画效果可屏蔽,同时原系统自带动画效果,可叠加,这是两种不同的效果,可以互补性的单个使用 9、设计了五种主题颜色,各人可以针对图形颜色和背景色进行更好的搭配,在用户项目中,可以自己添加新的主题。 10、扩展了时间轴的应用,在新的DateTimeChart中可以通过鼠标平移和缩放时间轴,并测试了两个例子用于动态显示历史曲线,一个是外部定时更新,一个是内部定时更新 11、对LineDataPoint样式进行了设计,现在可以选择线图的点样式(如空心圆、五角星、三角形,矩形等),同时这些不同的点样式可以体现在Legend上,从而实现颜色和图形的双重区分。 12、对饼图的标签排布进行了深度扩展,借鉴了Telerik 饼图的标签排布规则,重新调整了标签排布,现在饼图标签在各种情况下都不会发生重叠,个人感觉比Visifire的饼图标签排布要好,虽然Visifire的饼图标签不会重叠,但连接线可能会出现重叠 13、借鉴了Visifire的标签智能适应,对各种Chart图的标签显示进行了重新定位,现在柱状图/Bar图的标签显示可以自行决定是水平排布还是垂直排布,是位于内部还是位于外部等等,而区域图的标签则使用了Win7窗口的文字区域背景的高斯模糊技巧,这样可以适应各种背景,而Visifire的标签色则通过底部背景色的计算来确定前景色,测试后发现在某些中性色下显示不理想,在Y轴方向上,标签文字能自适应显示。 14、轴标签和数据点值标签都添加了格式化字符串属性的设定 15、轴添加了交替颜色显示设定 16、增加了一些新的Chart类型:Stock/AreaSpline/AreaStepLine/RangeArea/RangeSplineArea/Stacked100AreaSpline/StackedAreaSpline 对Candlestick进行了小幅的调整,现在宽度自适应,以及适应中国的红涨绿跌股市颜色

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧