XAML:UserControl内のコントロールインスタンスにName属性つけれないエラー
WPF を勉強していてまた躓いたので書き記す。
タイトルのとおり、UserControl を XAML で作って内部コードも書いていざメインの XAML で使おうとしたらエラーをはかれた。 どうやら仕様っぽいので今後も躓かないよう気を付ける。
とりあえず、ベターな解決策から言ってしまうと「 UserControl 使わずにカスタムコントロール使え」。
目次
下記のように、Name 属性つけれませんとエラーが出ていた。 X とか ? なとこはコントロールの名前とか入る。 要素 'XXXXXX' で Name 属性値 '??????' を設定することはできません。'XXXXXX' は、要素 '@@@@@' のスコープ内にあり、この要素には、別のスコープで定義されたときに既に名前が登録されています。 書いてた UserControl とメインの XAML は下記のとおり。 いろいろ調べた結果、やはりここで困った先駆者様がおり、そこに解決策があった。
大変助かったので引用としてリンクをば。 上記の先駆者様も調べて見つけたのは海外のブログとかなんで、自分ももっとググり力を上げてかないと・・・。 とりあえず、一番はっきりと解決策が書いてあって、かつ信用度の高いのが下記だった。 How to create a WPF UserControl with Named content? この記事によると、解決策は2つ。 1の解決策とか本当ににわかには信じ難いが、試しにゴリゴリ書いてみたところ、エラーなくビルドできた。
つまり仕様っぽいという・・・マジかい・・・。 独自 UI 作っていろいろしたいとき、UserControl はやめてカスタムコントロールを使うこと。
確かにコードでデザインすればいいのだが、XAMLのコンセプトから考えて、デザインとコードはできるだけ分離すべきなんで。 それにしても、UserControl 使いまくってツールが出来上がってからこの事実に気づいたら間違いなく発狂する事実だこれ。発生していたエラー
<UserControl x:Class="WindowsXaml_Chapter8.UserControls.ErrorUserControl"
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:WindowsXaml_Chapter8.UserControls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition x:Name="rowdef1" Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition x:Name="rowdef2" Height="0" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="coldef1" Width="*" MinWidth="100"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition x:Name="coldef2" Width="*" MinWidth="100" />
</Grid.ColumnDefinitions>
<Grid Name="grid1"
Grid.Row="0"
Grid.Column="0"/>
<Thumb Name="thumb"
Grid.Row="0"
Grid.Column="1"
Width="12"/>
<Grid Name="grid2"
Grid.Row="0"
Grid.Column="2"/>
</Grid>
</UserControl>
static ErrorUserControl()
{
Child1Property = DependencyProperty.Register(nameof(Child1), typeof(UIElement), typeof(ErrorUserControl), new PropertyMetadata(null, onChildChanged));
Child2Property = DependencyProperty.Register(nameof(Child2), typeof(UIElement), typeof(ErrorUserControl), new PropertyMetadata(null, onChildChanged));
OrientationProperty = DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(ErrorUserControl), new PropertyMetadata(Orientation.Horizontal, onOrientationChanged));
SwapChildrenProperty = DependencyProperty.Register(nameof(SwapChildren), typeof(bool), typeof(ErrorUserControl), new PropertyMetadata(false, onSwapChildrenChanged));
MinimumSizeProperty = DependencyProperty.Register(nameof(MinimumSize), typeof(double), typeof(ErrorUserControl), new PropertyMetadata((double)200, onMinimumSizeChanged));
}
public ErrorUserControl()
{
InitializeComponent();
}
<local_Control:ErrorUserControl x:Name="splitContainer"
Orientation="{Binding Orientation}"
SwapChildren="{Binding SwapEditAndDisplay}"
MinimumSize="200"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
<local_Control:ErrorUserControl.Child1>
<local:TabbableTextBox x:Name="editBox"
AcceptsReturn="True"
FontSize="{Binding FontSize}"
TabSpaces="{Binding TabSpaces}"
TextChanged="editBox_TextChanged"
SelectionChanged="editBox_SelectionChanged"/>
</local_Control:ErrorUserControl.Child1>
<local_Control:ErrorUserControl.Child2>
<local_Control:RulerContainer x:Name="resultContainer"
ShowRuler="{Binding ShowRuler}"
ShowGridLines="{Binding ShowGridLines}"/>
</local_Control:ErrorUserControl.Child2>
</local_Control:ErrorUserControl>
解決策
#region コンストラクタ
static SplitContainer2()
{
Child1Property = DependencyProperty.Register(nameof(Child1), typeof(UIElement), typeof(SplitContainer2), new PropertyMetadata(null, onChildChanged));
Child2Property = DependencyProperty.Register(nameof(Child2), typeof(UIElement), typeof(SplitContainer2), new PropertyMetadata(null, onChildChanged));
OrientationProperty = DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(SplitContainer2), new PropertyMetadata(Orientation.Horizontal, onOrientationChanged));
SwapChildrenProperty = DependencyProperty.Register(nameof(SwapChildren), typeof(bool), typeof(SplitContainer2), new PropertyMetadata(false, onSwapChildrenChanged));
MinimumSizeProperty = DependencyProperty.Register(nameof(MinimumSize), typeof(double), typeof(SplitContainer2), new PropertyMetadata((double)200, onMinimumSizeChanged));
}
public SplitContainer2()
{
//InitializeComponent();
#region メインGridの設定
mMainGrid = new Grid();
mRowDef1 = new RowDefinition
{
Height = new GridLength(1, GridUnitType.Star)
};
mRowDef2 = new RowDefinition
{
Height = new GridLength(1, GridUnitType.Auto)
};
mRowDef3 = new RowDefinition
{
Height = new GridLength(0)
};
mMainGrid.RowDefinitions.Add(mRowDef1);
mMainGrid.RowDefinitions.Add(mRowDef2);
mMainGrid.RowDefinitions.Add(mRowDef3);
mColDef1 = new ColumnDefinition
{
Width = new GridLength(1, GridUnitType.Star),
MinWidth = 100
};
mColDef2 = new ColumnDefinition
{
Width = new GridLength(1, GridUnitType.Auto)
};
mColDef3 = new ColumnDefinition
{
Width = new GridLength(1, GridUnitType.Star),
MinWidth = 100
};
mMainGrid.ColumnDefinitions.Add(mColDef1);
mMainGrid.ColumnDefinitions.Add(mColDef2);
mMainGrid.ColumnDefinitions.Add(mColDef3);
#endregion
#region 子要素の設定
// grid1
mGrid1 = new Grid();
Grid.SetRow(mGrid1, 0);
Grid.SetColumn(mGrid1, 0);
// grid2
mGrid2 = new Grid();
Grid.SetRow(mGrid2, 0);
Grid.SetColumn(mGrid2, 2);
// mThumb
mThumb = new Thumb
{
Width = 12
};
mThumb.DragStarted += mThumb_DragStarted;
mThumb.DragDelta += mThumb_DragDelta;
Grid.SetRow(mThumb, 0);
Grid.SetColumn(mThumb, 1);
#endregion
mMainGrid.Children.Add(mGrid1);
mMainGrid.Children.Add(mGrid2);
mMainGrid.Children.Add(mThumb);
Content = mMainGrid;
}
#endregion
結論