自定义控件只能实例化一次

时间:2012-03-08 13:49:51

标签: wpf vb.net xaml mvvm custom-controls

我是WPF和自定义控件的新手。

我已经在VB中使用WPF和MVVM实现了一个基于Davids示例的自定义控件:http://davidowens.wordpress.com/2009/02/18/wpf-search-text-box/

我有一个自定义控件库和对我的项目的引用来实现我的控件。 我通过XAML在View中实现了我的控制:

修改

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:l="clr-namespace:UIControls;assembly=UIControls"
mc:Ignorable="d"
x:Class="LoginView"
x:Name="LoginView"
Width="457" Height="216" Visibility="Visible" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors">

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="0.7*"/>
        <ColumnDefinition Width="3*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <l:ExpandedTextBox Name="UsernameText" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="10,0,5,5" />

</Grid>

一旦一切正常,我实例化自定义控件时

 <l:ExpandedTextBox Name="UsernameText" />

但是当我尝试在同一个View中实例化它两次时,我得到一个错误代码:

Error 1 Cannot create an instance of "ExpandedTextBox"

修改

带有错误的XAML代码如下所示:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:l="clr-namespace:UIControls;assembly=UIControls"
mc:Ignorable="d"
x:Class="LoginView"
x:Name="LoginView"
Width="457" Height="216" Visibility="Visible" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors">

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="0.7*"/>
        <ColumnDefinition Width="3*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

   <l:ExpandedTextBox Name="UsernameText" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="10,0,5,5" />

   <l:ExpandedTextBox Name="Password" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Margin="10,0,5,5" />

</Grid>

我将第二个自定义控件命名为不同,我的第一个自定义控件仍能正常工作。 该错误仅出现在第二个自定义控件“密码”中。

相应的Generic.xaml文件如下所示:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:UIControls">

<SolidColorBrush x:Key="ExpandedTextBox_Background" Color="White" />
<SolidColorBrush x:Key="ExpandedTextBox_Foreground" Color="Black" />
<LinearGradientBrush x:Key="ExpandedTextBox_Border" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Color="#FFABADB3" Offset="0.05" />
    <GradientStop Color="#FFE2E3EA" Offset="0.07" />
    <GradientStop Color="#FFE3E9EF" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ExpandedTextBox_BorderMouseOver" StartPoint="0,0" EndPoint="0,1">
    <GradientStop Color="#FF5C97C1" Offset="0.05" />
    <GradientStop Color="#FFB9D7EB" Offset="0.07" />
    <GradientStop Color="#FFC7E2F1" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="ExpandedTextBox_SearchIconBorder" Color="White" />
<SolidColorBrush x:Key="ExpandedTextBox_SearchIconBackground" Color="White" />
<LinearGradientBrush x:Key="ExpandedTextBox_SearchIconBorder_MouseOver" StartPoint="0,0" EndPoint="0,1" >
    <GradientStop Color="#FFFFFFFF" Offset="0" />
    <GradientStop Color="#FFE5F4FC" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ExpandedTextBox_SearchIconBackground_MouseOver" StartPoint="0,0" EndPoint="0,1" >
    <GradientStop Color="#FFE7F5FD" Offset="0" />
    <GradientStop Color="#FFD2EDFC" Offset="0.5" />
    <GradientStop Color="#FFB6E3FD" Offset="0.51" />
    <GradientStop Color="#FF9DD5F3" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ExpandedTextBox_SearchIconBorder_MouseDown" StartPoint="0,0" EndPoint="0,1" >
    <GradientStop Color="#FFFFFFFF" Offset="0" />
    <GradientStop Color="#FFE5F4FC" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ExpandedTextBox_SearchIconBackground_MouseDown" StartPoint="0,0" EndPoint="0,1" >
    <GradientStop Color="#FFE7F5FD" Offset="0" />
    <GradientStop Color="#FFD2EDFC" Offset="0.5" />
    <GradientStop Color="#FFB6E3FD" Offset="0.51" />
    <GradientStop Color="#FF9DD5F3" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="ExpandedTextBox_LabelTextColor" Color="Gray" />



<Style x:Key="{x:Type l:ExpandedTextBox}" TargetType="{x:Type l:ExpandedTextBox}">
    <Setter Property="Background" Value="{StaticResource ExpandedTextBox_Background}" />
    <Setter Property="BorderBrush" Value="{StaticResource ExpandedTextBox_Border}" />
    <Setter Property="Foreground" Value="{StaticResource ExpandedTextBox_Foreground}" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="LabelText" Value="Username" />
    <Setter Property="FontSize" Value="16" />
    <Setter Property="Text" Value="" />
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="LabelTextColor" Value="{StaticResource ExpandedTextBox_LabelTextColor}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type l:ExpandedTextBox}">

                <Border x:Name="Border"
                   Padding="2"
                   Background="{TemplateBinding Background}"
                   BorderBrush="{TemplateBinding BorderBrush}"
                   BorderThickness="{TemplateBinding BorderThickness}">

                    <Grid x:Name="LayoutGrid">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualHeight}" />
                        </Grid.ColumnDefinitions>
                        <ScrollViewer x:Name="PART_ContentHost" Grid.Column="0" />

                        <Label x:Name="LabelText"
                          Grid.Column="0"
                          Foreground="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelTextColor}"
                          Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelText}"
                          Padding="2,0,0,0"
                          FontStyle="Italic" />

                        <Border x:Name="PART_SearchIconBorder"
                          Grid.Column="2"
                          Visibility="Collapsed"
                          BorderThickness="1"
                          Padding="1"
                          VerticalAlignment="Stretch"
                          HorizontalAlignment="Stretch"
                          BorderBrush="{StaticResource ExpandedTextBox_SearchIconBorder}"
                          Background="{StaticResource ExpandedTextBox_SearchIconBackground}">

                            <Image x:Name="SearchIcon"
                                Stretch="None"
                                Width="Auto"
                                Height="Auto"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                Source="pack://application:,,,/UIControls;component/Images/clear.png" />

                        </Border>
                    </Grid>
                </Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="BorderBrush" Value="{StaticResource ExpandedTextBox_BorderMouseOver}" />
                    </Trigger>
                    <Trigger Property="IsKeyboardFocusWithin" Value="True">
                        <Setter Property="BorderBrush" Value="{StaticResource ExpandedTextBox_BorderMouseOver}" />
                    </Trigger>
                    <Trigger Property="HasText" Value="True">
                        <Setter Property="Visibility" TargetName="LabelText" Value="Hidden" />
                        <Setter Property="Visibility" TargetName="PART_SearchIconBorder" Value="Visible" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" SourceName="PART_SearchIconBorder" Value="True">
                        <Setter Property="HasClicked" Value="True" />
                        <Setter Property="Background" TargetName="PART_SearchIconBorder" Value="#FFF0F5" />
                    </Trigger>

                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
</ResourceDictionary>

ExpandedTextBox VB文件如下所示:

Imports System.Windows.Controls.Primitives
Imports System.ComponentModel


Public Class ExpandedTextBox
Inherits System.Windows.Controls.TextBox


Public Property LabelTextProperty As DependencyProperty = DependencyProperty.Register("LabelText", GetType(String), GetType(ExpandedTextBox))
Public Property LabelTextColorProperty As DependencyProperty = DependencyProperty.Register("LabelTextColor", GetType(Brush), GetType(ExpandedTextBox))
Public Property HasTextPropertyKey As DependencyProperty = DependencyProperty.Register("HasText", GetType(Boolean), GetType(ExpandedTextBox), New PropertyMetadata())
Public Property HasTextProperty As DependencyProperty = HasTextPropertyKey
Public Property HasClickedPropertyKey As DependencyProperty = DependencyProperty.Register("HasClicked", GetType(Boolean), GetType(ExpandedTextBox), New PropertyMetadata())
Public Property HasClickedProperty As DependencyProperty = HasClickedPropertyKey

Public Property HasClicked As Boolean
    Get
        Return CType(GetValue(HasClickedProperty), Boolean)
    End Get
    Set(ByVal value As Boolean)
        SetValue(HasClickedProperty, value)
    End Set
End Property
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Input.MouseButtonEventArgs)
    If HasClicked = True Then
        Me.Text = ""
    Else
        MyBase.OnMouseDown(e)
    End If

End Sub


Public Property LabelText As String
    Get
        Return CType(GetValue(LabelTextProperty), String)
    End Get
    Set(ByVal value As String)
        SetValue(LabelTextProperty, value)
    End Set
End Property

Public Property LabelTextColor As Brush
    Get
        Return CType(GetValue(LabelTextColorProperty), Brush)
    End Get
    Set(ByVal value As Brush)
        SetValue(LabelTextColorProperty, value)
    End Set
End Property

Public Property HasText As Boolean
    Get
        Return CType(GetValue(HasTextProperty), Boolean)
    End Get
    Set(ByVal value As Boolean)
        SetValue(HasTextProperty, value)
    End Set
End Property


Shared Sub New()
    DefaultStyleKeyProperty.OverrideMetadata(GetType(ExpandedTextBox), New FrameworkPropertyMetadata(GetType(ExpandedTextBox)))
End Sub

Protected Overrides Sub OnTextChanged(ByVal e As TextChangedEventArgs)
    MyBase.OnTextChanged(e)
    HasText = Text.Length <> 0
End Sub


End Class

为什么我不能在视图中两次创建相同的自定义控件?
提前谢谢!

2 个答案:

答案 0 :(得分:1)

这可能是因为您指定了x:Name UserControl的<{1}}属性。

你正在添加控件的网格是否知道它们的名称,这就是为什么如果它在其子集合中使用相同的x:Name检测到多个控件时会抛出异常。

答案 1 :(得分:1)

我们用Rich的评论解决了这个问题。谢谢你!

问题是依赖属性,它们未在VB文件中设置为共享。新的工作文件看起来像这样。

Imports System.Windows.Controls.Primitives
Imports System.ComponentModel


Public Class ExpandedTextBox
Inherits System.Windows.Controls.TextBox


Public Shared Property LabelTextProperty As DependencyProperty
Public Shared Property LabelTextColorProperty As DependencyProperty
Public Shared Property HasTextPropertyKey As DependencyProperty
Public Shared Property HasTextProperty As DependencyProperty
Public Shared Property HasClickedPropertyKey As DependencyProperty
Public Shared Property HasClickedProperty As DependencyProperty


Shared Sub New()
    DefaultStyleKeyProperty.OverrideMetadata(GetType(ExpandedTextBox), New FrameworkPropertyMetadata(GetType(ExpandedTextBox)))
    LabelTextProperty = DependencyProperty.Register("LabelText", GetType(String), GetType(ExpandedTextBox))
    LabelTextColorProperty = DependencyProperty.Register("LabelTextColor", GetType(Brush), GetType(ExpandedTextBox))
    HasTextPropertyKey = DependencyProperty.Register("HasText", GetType(Boolean), GetType(ExpandedTextBox), New PropertyMetadata())
    HasTextProperty = HasTextPropertyKey
    HasClickedPropertyKey = DependencyProperty.Register("HasClicked", GetType(Boolean), GetType(ExpandedTextBox), New PropertyMetadata())
    HasClickedProperty = HasClickedPropertyKey
End Sub


Public Property HasClicked As Boolean
    Get
        Return CType(GetValue(HasClickedProperty), Boolean)
    End Get
    Set(ByVal value As Boolean)
        SetValue(HasClickedProperty, value)
    End Set
End Property
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Input.MouseButtonEventArgs)
    If HasClicked = True Then
        Me.Text = ""
    Else
        MyBase.OnMouseDown(e)
    End If

End Sub


Public Property LabelText As String
    Get
        Return CType(GetValue(LabelTextProperty), String)
    End Get
    Set(ByVal value As String)
        SetValue(LabelTextProperty, value)
    End Set
End Property

Public Property LabelTextColor As Brush
    Get
        Return CType(GetValue(LabelTextColorProperty), Brush)
    End Get
    Set(ByVal value As Brush)
        SetValue(LabelTextColorProperty, value)
    End Set
End Property

Public Property HasText As Boolean
    Get
        Return CType(GetValue(HasTextProperty), Boolean)
    End Get
    Set(ByVal value As Boolean)
        SetValue(HasTextProperty, value)
    End Set
End Property



Protected Overrides Sub OnTextChanged(ByVal e As TextChangedEventArgs)
    MyBase.OnTextChanged(e)
    HasText = Text.Length <> 0
End Sub


End Class

感谢所有的贡献!

很棒的StackOverflow!

相关问题