2010-07-16 48 views
0

我是這個論壇的新手。 我有一個用c#和xaml定義的自定義用戶控件。當我把這個控件放到WPF窗口中時,它就起作用了。即使我可以編輯xaml代碼標籤並插入我的控件。但是當我在c#代碼中使用我的控件時,它不工作。爲什麼我不能在c#中使用我自定義的WPF控件代碼

這裏是我的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> 

,這裏是我的C#控制定義

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#訪問此控制研究

WellImage image = new WellImage();    
     image.Height = 40; 
     image.Width = 40; 
     image.Margin = new Thickness(30, 30, 30, 30); 
     image.VerticalAlignment = VerticalAlignment.Top; 
     image.HorizontalAlignment = HorizontalAlignment.Left; 
     image.Content = "WellButton"; 
     grid.Children.Insert(0, image); 
     grid.Background = Brushes.LightBlue; 
     grid.Width = 120; 
     grid.Height = 100; 
     grid.VerticalAlignment = VerticalAlignment.Top; 
     grid.HorizontalAlignment = HorizontalAlignment.Left; 
     gridPartialedMicroPlate.Children.Insert(0, grid); 

爲什麼我無法訪問我的控制權?

+0

當您嘗試以編程方式調用它時,收到的錯誤消息是什麼? – Aaronontheweb 2010-07-16 04:26:12

+0

嗨,彼得,你的代碼編譯?我的意思是你展示你如何試圖訪問它的代碼,是不是編譯? IntelliSense在創建後是否找到圖像對象? 還是你的意思是,如果你使用調試器,你永遠不會看到它構造? – jameschinnock 2010-07-16 06:20:03

回答

3

你有三個主要問題:

  1. 你InnerBackground,OuterBackground和WellBorder總是空,
  2. 您的模板沒有ContentPresenter,
  3. 你的省略號是零大小

空筆刷

InnerBackground,OuterBackground和WellBorder爲null的原因是您在構造函數中將它們設置爲null。例如,這行是一個問題:

InnerBackGround = (RadialGradientBrush)this.Resources["WellSelectedInnerCircleBrush"]; 

有兩個問題與該行:

  1. 它採用this.Resoures [],其中僅看在當地的ResourceDictionary。爲了做到相當於StaticResource,你必須查看祖先的ResourceDictionaries,這意味着調用FindResource()。
  2. 它在構造函數中,所以它在控件有父項之前執行。由於此時沒有祖先,即使FindResource()也不適合你。

解決這個問題的最佳解決方案是在構造函數中,而不是設置在樣式這些屬性:

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

如果你真的想這樣做,在構造函數中,你可以構造一個DynamicResource參考有:

SetValue(InnerBackgroundProperty, 
    new DynamicResourceExtension("WellSelectedInnerCircleBrush") 
    .ProvideValue()); 

缺少ContentPresenter

如果您在模板中包含了一個ContentPresenter,那麼即使橢圓是不可見的,也會看到字符串「WellButton」。

您應該考慮修改ControlTemplate以包含ContentPresenter以顯示Content屬性。分配Content屬性似乎沒有意義,但不顯示它。

零大小的橢圓,

每個橢圓被設定爲寬度=「自動」 HEIGHT =「自動」時,這對於橢圓形是指大小爲零。這將使你的橢圓不可見,即使他們有刷子。

此外網格設置爲寬度=「自動」高度=「自動」,這意味着將其內容擠入儘可能最小的空間。這意味着如果WellButton被設置爲VerticalAlignment =「Stretch」或者Horizo​​ntalAlignment =「Stretch」,它會固執地拒絕實際拉伸。這在自定義控件中是一件壞事。

移除兩個你認爲寬度=「自動」和高度=「自動」的地方,而是保持高度和寬度不變。

其他問題和挑剔

你的第二個橢圓具有StrokeThickness =這是沒有意義的,因爲我沒有中風「0」。爲什麼不放棄它?因爲沒有RenderTransform,因此RenderTransformOrigin也是這樣。

您的第一個橢圓不需要指定Horizo​​ntalAlignment =「Stretch」VerticalAlignment =「Stretch」,因爲這是默認設置。

您的綁定過於複雜:

  1. ,則可以省略「PATH =」除非路徑中包含附加屬性。
  2. ,則可以省略「模式=單向」,因爲這是默認的,但最重要的是:
  3. 您可以使用TemplateBinding,而不是它是乾淨多了:

TemplateBinding語法:

<Ellipse Stroke="{TemplateBinding WellBorder}" 
     ... /> 

您的第二個橢圓上的邊距非常大,即使您的C#代碼中的Width =「40」Height =「40」被尊重(因爲Auto問題已修復),橢圓仍然沒有大小。具有這種不尋常邊緣的橢圓似乎也很奇怪。

Nitpick:「背景」是一個單一的英語單詞,它的中間沒有大寫字母G.

+0

優秀的答案! +1! – jameschinnock 2010-07-16 06:26:36

+0

是的,它是一個很好的答案。謝謝雷。 – Peter 2010-07-19 04:18:35

+0

@彼得:很高興我能幫忙。順便說一句,如果您認爲這是您問題的最佳答案,則應該點擊對號將其標記爲最佳答案。這給了我們兩個「代表」點,它帶來了你的「答案%」,並且幫助其他人認識到最佳答案。 – 2010-07-20 01:47:59

相關問題