首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么WPF用对角线分割来呈现我的控件?

为什么WPF用对角线分割来呈现我的控件?
EN

Stack Overflow用户
提问于 2011-01-14 20:22:14
回答 5查看 1.7K关注 0票数 7

WPF似乎正在对角拆分我的控件。我做错了什么?这个问题在蓝色按钮上比较清楚,但在右边的按钮上仍然很明显。

奇怪的是,kaxaml正确地呈现了按钮。WPF的设计师似乎从来没有。当我在独立的“WpfApplication1”中运行示例代码时,它将正确呈现。然而,在我的应用程序中,我得到了对角线“剪切”。可能值得一提的是,在运行时,WPF似乎没有始终如一地应用切片效果,有时它们正确地呈现!

更新1:一条线索!它只会影响按钮!当我创建一个独立的Border并将标签作为它的内容时,没有切片效果?!所以这不是xaml本身,而是什么神奇的按钮?!大声地想一想,这与不完全覆盖默认按钮模板有关吗?

更新2:,好吧,这一分钟变得更奇怪了。这和影子效应有关。似乎要绘制的具有效果的第一种控件类型(BitmapEffect或WPF4.0效果)与该类型的所有其他控件实例一样被拆分。例如,这里有一个带有可爱的红色阴影的DatePicker,它以对角线方式将DatePicker控件分割开来,之后按钮就很好了,尽管也有应用于它的效果。

如果我不应用效果,就不会分割控制。如果我绘制了一个具有效果的控件,则该控件将被拆分,并且不同类型的后续控件都很好。但是,如果您有两个或三个相同类型的控件,它们也会被拆分。如果一个按钮被分割,页面上的所有按钮也会被分割。

这肯定与我的GPU或图形驱动程序有关。我今天早上更新了它们,但没有joy。(我正在使用Radeon Mobility 5650,v8.683.2.0)。如果这个问题是孤立于我的个人电脑,我想它不是世界末日。也许,我可以在它自己的游戏中通过在每一页顶部的随机路径像素上画一个透明的效果来击败它。

更新3

哦,亲爱的。我现在已经在另一台PC上复制了这个,所以它不是我的显卡或驱动程序。

代码语言:javascript
复制
        <StackPanel.Resources>

            <!-- Background for button when IsDefault  true"-->
            <LinearGradientBrush x:Key="DefaultButtonFill" StartPoint="0.5, 0" EndPoint="0.5, 1">
                <GradientStop Color="#FFDFEDEC" Offset="0"/>
                <GradientStop Color="#FF92B1E3" Offset="0.4"/>
                <GradientStop Color="#FF749EE0" Offset="0.5"/>
                <GradientStop Color="#94DDF6" Offset="1"/>
            </LinearGradientBrush>

            <!-- default button background -->
            <LinearGradientBrush x:Key="NotDefaultButtonFill" StartPoint="0.5, 0" EndPoint="0.5, 1">
                <GradientStop Color="#FFEFEFF5" Offset="0"/>
                <GradientStop Color="#FFE1E1E6" Offset="0.4"/>
                <GradientStop Color="#FFC7CBD0" Offset="0.5"/>
                <GradientStop Color="#FFE8ECEE" Offset="1"/>
            </LinearGradientBrush>

            <Style TargetType="Button">
                <Setter Property="FontSize" Value="14"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="Button">
                            <Border x:Name="border"
                        CornerRadius="12"
                        Background="{StaticResource NotDefaultButtonFill}"
                        Padding="25 8"
                        Margin="10"
                        Cursor="Hand">


                                <Border.BitmapEffect>
                                    <DropShadowBitmapEffect x:Name="shadow" Direction="280" Color="Black"  ShadowDepth="2" Opacity=".6"/>
                                </Border.BitmapEffect>

                                <!--
                    <Border.Effect>
                        <DropShadowEffect x:Name="shadow" Direction="280" Color="Black"  ShadowDepth="2" Opacity=".6"/>
                    </Border.Effect>-->

                                <ContentPresenter 
                            HorizontalAlignment="Center"
                            VerticalAlignment="Center"
                            Content="{TemplateBinding Content}" />

                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsDefault" Value="True">
                                    <Setter TargetName="border" Property="Background" Value="{StaticResource DefaultButtonFill}"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter TargetName="border" Property="Background" Value="LightGray"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>





        </StackPanel.Resources>

        <StackPanel Orientation="Horizontal">
            <Button>Normal</Button>
            <Button IsDefault="True">IsDefault</Button>
        </StackPanel>
    </StackPanel>
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-10-24 12:14:48

这是由于WPF和ATI图形驱动程序之间的一些微妙交互导致的错误。这似乎发生在使用DropShadowEffect时,元素并不完全定位在像素边界上。

如果在所讨论的元素(或适当的样式)上设置了UseLayoutRounding="True“,那么在很多情况下,这似乎解决了这个问题,但并不是全部。另一件要做的事情是确保你没有故意将元素定位在半像素(例如,通过使用小数边距-如果你在表达式混合中移动元素,这可能会发生)。

下面是一个简单的复制案例:

代码语言:javascript
复制
 <UserControl
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <UserControl.Resources>
     <Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
         <Setter Property="Width" Value="28"/>
         <Setter Property="Height" Value="28"/>
         <Setter Property="Template">
             <Setter.Value>
                 <ControlTemplate TargetType="{x:Type Button}">
                     <Border x:Name="Border" Background="Transparent">
                         <Grid Margin="{TemplateBinding Padding}">
                         <ContentPresenter x:Name="contentPresenter" VerticalAlignment="Center"
                                           HorizontalAlignment="Center">
                           <ContentPresenter.Effect>
                             <DropShadowEffect BlurRadius="13" Color="Black" Opacity="1" ShadowDepth="0" Direction="0"/>
                           </ContentPresenter.Effect>
                         </ContentPresenter>
                         </Grid>
                     </Border>
                 </ControlTemplate>
             </Setter.Value>
         </Setter>
     </Style>
   </UserControl.Resources>
   <Grid>  
     <Button x:Name="MinimizeButton"
                Style="{StaticResource ButtonStyle}">
            <Rectangle x:Name="MinimizeIcon"
                       Width="11"
                       Height="2"
                       HorizontalAlignment="Center"
                       Margin="0,7,0,0"
                       VerticalAlignment="Bottom"
                       Stroke="Gray"
                       StrokeThickness="2"/>
    </Button>
   </Grid>
 </UserControl>

如果您将其插入卡萨姆并左右移动缩放滑块,则当缩放设置为150时,您应该会看到分割显示。

如果将<Setter Property="UseLayoutRounding" Value="True"/>添加到按钮样式,则缩放级别150将正确呈现,但拆分将出现在缩放级别300。

这就是为什么我说我的工作--并不是在所有情况下都有效--如果你只需要在一个固定大小上显示你的内容,UseLayoutRounding可能会在这个尺寸上隐藏问题,但是如果你的应用程序中有缩放功能,你可能有时仍然会遇到这个问题。

微软论坛上,以下是ATI对这个问题的看法:

根本原因是WPF4.0将使用DX10风格的纹理坐标寻址来使用点过滤器(圆到最近)呈现文本,同时使用DX9 API。我们遵循DX9规则(截断到最近),因为这是DX9驱动程序。如果我们强制使用HW风格的DX10纹理坐标,这个问题就会消失。然而,我认为微软应该遵循自己的规则,在使用DX9 API的同时,使用DX9风格的纹理坐标寻址。“

如果你也能重复这个问题,那就去把你的投票结果加到我在连接上添加的问题上,这样我们就可以解决这个问题了--尽管我不抱太大希望;微软对类似问题表示,他们认为这项工作暂时是可以接受的。

票数 3
EN

Stack Overflow用户

发布于 2011-12-21 22:43:00

当WPF向位于部分像素偏移量的树呈现效果时,就会出现核心问题。对于硬件路径,我们可以做两种基本的方法:

1)创建与屏幕像素相对应的中间纹理,并在该纹理中的部分像素偏移处呈现树。然后,当将该中间部分传输回屏幕时,我们可以使用对像素对齐的四元,并使用简单的最近邻采样,因为内容是像素对齐的。

2)创建一个与树的边界相对应的中间纹理,并在该纹理中的0偏移量处呈现树。然后,当将中间部分传送回屏幕时,我们需要使用一个覆盖部分像素的四象素。由于四象素可以覆盖部分像素,所以采样模式很重要。像NearestNeighbor这样的采样模式会导致可能依赖GPU的混叠效应。

WPF选择了#2和强制最近邻采样,除非具有偏移或缩放(最常见的是旋转)以外的任何变换的树强制双线性采样。这与软件栅格化路径有细微差别,后者将使用对树有效的插值模式,除非树具有偏移量或比例以外的变换,在这种情况下,它还强制进行双线性采样。

我们通过将硬件路径与软件路径相一致来“解决”这个问题。这意味着我们将尊重对正在呈现的树有效的采样模式。这可以从带有RenderOptions.BitmapScalingMode附加属性的托管代码中设置。默认值为线性,这是当四像素覆盖部分像素时一种更适合的采样模式。然而,它确实引入了一个明显的模糊--但与软件栅格化所产生的一样。

对于4.0,有几个解决办法:

1)防止元素树定位在部分像素上。例如,可以在定位元素的容器上将UseLayoutRounding属性设置为true。

2)采用小旋转,使渲染路径采用双线性插值。这可能非常小,例如带有RenderTransform的<RotateTransform Angle="0.00000000001"/>

请注意,自定义ShaderEffects使用具有可配置采样模式的显式取样器。

客户可以通过将RenderOptions.BitmapScalingMode附加属性设置为"NearestNeighbor“来获得当前行为。请注意,即使这将被忽略,如果树是旋转,并将使用双线性抽样代替。确实,在某些GPU上,像DropShadow这样的效果在使用NearestNeighbor采样时可能会遇到混叠伪影。

还请注意,当对图像应用效果时,相同的RenderOptions.BitmapScalingMode附加属性值将用于图像内容和效果中间纹理。如果您想要一个带有NearestNeighbor采样的图像,但是要使用线性采样,那么您需要将效果应用到图像的容器中,例如包含图像的简单画布。

票数 3
EN

Stack Overflow用户

发布于 2011-01-14 21:01:47

尝试按以下方式安排嵌套:

代码语言:javascript
复制
<StackPanel Orientation="Horizontal">
   <StackPanel.Resources>
      ...
   </StackPanel.Resources>
   <Button>Normal</Button>
   <Button IsDefault="True">IsDefault</Button>
</StackPanel>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4695538

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档