C# 为什么我不能在c代码中使用自定义WPF控件

C# 为什么我不能在c代码中使用自定义WPF控件,c#,wpf,xaml,C#,Wpf,Xaml,我是这个论坛的新手。 我有一个使用c#和xaml定义的自定义用户控件。当我dag并将此控件放到WPF窗口时,它会工作。甚至我也可以编辑xaml代码标记并插入我的控件。但是当我在c代码中使用我的控件时,它就不起作用了 这是我的xaml控件定义 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:local="clr-namespace:UserCont

我是这个论坛的新手。 我有一个使用c#和xaml定义的自定义用户控件。当我dag并将此控件放到WPF窗口时,它会工作。甚至我也可以编辑xaml代码标记并插入我的控件。但是当我在c代码中使用我的控件时,它就不起作用了

这是我的xaml控件定义

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:local="clr-namespace:UserControl"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">   
  <!-- Resource dictionary entries should be defined here. -->
  <Style TargetType="{x:Type local:WellImage}">
    <Setter Property="Focusable" Value="false" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:WellImage}">
          <Grid Width="Auto" Height="Auto">
            <Ellipse Stroke="{Binding Path=WellBorder, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
                     StrokeThickness="{Binding Path=WellBorderThickness, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
                     x:Name="Border" Width="Auto" Height="Auto"
                     HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                     Fill="{Binding Path=OuterBackGround, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" />
            <Ellipse StrokeThickness="0" Margin="25,37,25,18" RenderTransformOrigin="0.5,0.5"
                     Fill="{Binding Path=InnerBackGround, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
          </Grid>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace UserControl
{
  public class WellImage : System.Windows.Controls.Button
  {
    public static readonly DependencyProperty InnerBackGroundProperty = DependencyProperty.Register("InnerBackGround", typeof(RadialGradientBrush), typeof(WellImage));
    public static readonly DependencyProperty OuterBackGroundProperty = DependencyProperty.Register("OuterBackGround", typeof(RadialGradientBrush), typeof(WellImage));
    public static readonly DependencyProperty WellBorderProperty = DependencyProperty.Register("WellBorder", typeof(SolidColorBrush), typeof(WellImage));
    public static readonly DependencyProperty WellBorderThicknessProperty = DependencyProperty.Register("WellBorderThickness", typeof(double), typeof(WellImage));

    public WellImage()
    {
      // Insert code required on object creation below this point.
      InnerBackGround = (RadialGradientBrush)this.Resources["WellSelectedInnerCircleBrush"];
      OuterBackGround = (RadialGradientBrush)this.Resources["WellSelectedOuterCircleBrush"];
      WellBorder = (SolidColorBrush)this.Resources["NormalBackgroundBrush"];
      WellBorderThickness =2;
    }

    static WellImage()
    {
      //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class.
      //This style is defined in themes\generic.xaml
      DefaultStyleKeyProperty.OverrideMetadata(typeof(WellImage), new FrameworkPropertyMetadata(typeof(WellImage)));
    }

    public RadialGradientBrush InnerBackGround
    {
      get { return (RadialGradientBrush)GetValue(InnerBackGroundProperty); }
      set { SetValue(InnerBackGroundProperty, value); }
    }

    public RadialGradientBrush OuterBackGround
    {
      get { return (RadialGradientBrush)GetValue(OuterBackGroundProperty); }
      set { SetValue(OuterBackGroundProperty, value); }
    }

    public SolidColorBrush WellBorder
    {
      get { return (SolidColorBrush)GetValue(WellBorderProperty); }
      set { SetValue(WellBorderProperty, value); }
    }

    public double WellBorderThickness
    {
      get { return (double)GetValue(WellBorderThicknessProperty); }
      set { SetValue(WellBorderThicknessProperty, value); }
    }
  }
}
这就是通过c访问控制器的方法#


为什么我无法访问我的控件?

您有三个主要问题:

  • 您的InnerBackground、OuterBackground和WellOrder始终为空
  • 模板中没有ContentPresenter
  • 你的椭圆是零大小的
  • 空笔刷

    InnerBackground、OuterBackground和WellOrder为null的原因是您在构造函数中将它们设置为null。例如,这一行是一个问题:

    InnerBackGround = (RadialGradientBrush)this.Resources["WellSelectedInnerCircleBrush"]; 
    
    这一行有两个问题:

  • 它使用这个.resources[],它只在本地ResourceDictionary中查找。要执行与StaticResource等效的操作,必须查看祖先的ResourceDictionary,这意味着调用FindResource()
  • 它位于构造函数中,因此它在控件具有父控件之前执行。因为此时它没有祖先,所以即使FindResource()也不适合您
  • 此问题的最佳解决方案是在样式中而不是在构造函数中设置这些属性:

    <Style TargetType="{x:Type local:WellImage}">
      <Setter Property="Focusable" Value="false" /> 
      <Setter Property="InnerBackground" Value="{DynamicResource WellSelectedInnerCircleBrush}" />
      ...
    
    缺少ContentPresenter

    如果在模板中包含ContentPresenter,即使椭圆不可见,也会显示字符串“WellButton”

    您应该考虑修改控件模板以包含内容演示程序来显示内容属性。分配内容属性而不显示它似乎毫无意义

    零大小椭圆

    每个椭圆都设置了Width=“Auto”Height=“Auto”,这对于椭圆意味着零尺寸。这将使椭圆不可见,即使它们有画笔

    此外,网格设置为Width=“Auto”Height=“Auto”,这意味着将其内容压缩到尽可能小的空间中。这意味着,如果使用VerticalAlignment=“Stretch”或HorizontalAlignment=“Stretch”设置井按钮,它将顽固地拒绝实际拉伸。这在自定义控件中是一件坏事

    删除两个您说Width=“Auto”和Height=“Auto”的位置,并保留高度和宽度未设置

    其他问题和吹毛求疵

    你的第二个椭圆有strokehickness=“0”,这对我来说没有意义,因为没有笔划。为什么不把它删掉呢?由于没有RenderTransform,RenderTransformMorigin也一样

    第一个椭圆不需要指定HorizontalAlignment=“Stretch”VerticalAlignment=“Stretch”,因为这是默认值

    您的绑定太复杂了:

  • 除非路径包含附加属性,否则可以省略“Path=”
  • 您可以省略“Mode=OneWay”,因为这是默认值,但最重要的是:
  • 您可以使用更干净的TemplateBinding:
  • TemplateBinding语法:

    <Ellipse Stroke="{TemplateBinding WellBorder}"
             ... />
    
    
    
    第二个椭圆上的边距非常大,即使您的C#code中的Width=“40”Height=“40”得到遵守(因为自动问题已经解决),椭圆仍然没有大小。而且,有这样一个不寻常的边缘椭圆似乎很奇怪


    “背景”是一个英语单词,中间没有一个大写字母。

    你有三个主要问题:

  • 您的InnerBackground、OuterBackground和WellOrder始终为空
  • 模板中没有ContentPresenter
  • 你的椭圆是零大小的
  • 空笔刷

    InnerBackground、OuterBackground和WellOrder为null的原因是您在构造函数中将它们设置为null。例如,这一行是一个问题:

    InnerBackGround = (RadialGradientBrush)this.Resources["WellSelectedInnerCircleBrush"]; 
    
    这一行有两个问题:

  • 它使用这个.resources[],它只在本地ResourceDictionary中查找。要执行与StaticResource等效的操作,必须查看祖先的ResourceDictionary,这意味着调用FindResource()
  • 它位于构造函数中,因此它在控件具有父控件之前执行。因为此时它没有祖先,所以即使FindResource()也不适合您
  • 此问题的最佳解决方案是在样式中而不是在构造函数中设置这些属性:

    <Style TargetType="{x:Type local:WellImage}">
      <Setter Property="Focusable" Value="false" /> 
      <Setter Property="InnerBackground" Value="{DynamicResource WellSelectedInnerCircleBrush}" />
      ...
    
    缺少ContentPresenter

    如果在模板中包含ContentPresenter,即使椭圆不可见,也会显示字符串“WellButton”

    您应该考虑修改控件模板以包含内容演示程序来显示内容属性。分配内容属性而不显示它似乎毫无意义

    零大小椭圆

    每个椭圆都设置了Width=“Auto”Height=“Auto”,这对于椭圆意味着零尺寸。这将使椭圆不可见,即使它们有画笔

    此外,网格设置为Width=“Auto”Height=“Auto”,这意味着将其内容压缩到尽可能小的空间中。这意味着,如果使用VerticalAlignment=“Stretch”或HorizontalAlignment=“Stretch”设置井按钮,它将顽固地拒绝实际拉伸。这在自定义控件中是一件坏事

    删除两个您说Width=“Auto”和Height=“Auto”的位置,并保留高度和宽度未设置

    其他问题和吹毛求疵

    你的第二个椭圆有strokehickness=“0”,这对我来说没有意义,因为没有笔划。为什么不把它删掉呢?由于没有RenderTransform,RenderTransformMorigin也一样

    第一个椭圆不需要指定HorizontalAlignment=“Stretch”VerticalAlignment=“Stretch”,因为这是默认值

    您的绑定太复杂了:

  • 你可以省略t