0

私はこのXAMLを持っています:

<dxb:BarStaticItem>
  <TextBlock Text="{Binding MyStatusBarText}"></TextBlock>
</dxb:BarStaticItem> 

ただし、次のエラーが発生します。

Cannot add content to an object of type BarStaticItem

レンダリングされたアイテムの色やスタイルを変更するなど、これを修正するにはどうすればよいですか?

4

2 に答える 2

5

と仮定するBarStaticItemUserControl...

1 つの部分的な cs ファイルでコード ビハインドを使用しています。ここでは、(ほぼ) すべてが行われ、代わりにObservableCollectionof (または必要な要素) が使用されます。UIElement

1) という名前の関連する部分クラスを作成しBarStaticItem.Children.cs、必要な名前空間を追加します。

using System.Collections.ObjectModel; // ObservableCollection.
using System.Collections.Specialized; // NotifyCollectionChangedEventHandler.
using System.Windows.Markup; // [ContentProperty()]

2)ContentProperty部分クラス宣言の上にフラグを追加してから、 ChildrenProperty 宣言を追加します。

namespace YourNamespace.SubNamespace
{
    [ContentProperty("Children")] // <- here !
    public partial class BarStaticItem
    // (This is the related BarStaticItem.Children.cs file)
    {
        /// <summary>
        /// Gets the Children Property of this BarStaticItem.
        /// </summary>
        public ObservableCollection<UIElement> Children { get; private set; }
    }
}

3) 次に、cs ファイルのプライベート メソッドでObservableCollection プロパティの初期化子を作成します。

        private void RegisterChildrenObservation()
        {
            Children = new ObservableCollection<UIElement>();
            Children.CollectionChanged += 
                new NotifyCollectionChangedEventHandler(Children_CollectionChanged);
        }

4) カスタム UI Element のコンストラクターでその初期化子を呼び出します。

namespace YourNamespace.SubNamespace
{
    public partial class BarStaticItem : UserControl
    // (This is the base BarStaticItem.xaml.cs file)
    {
        public BarStaticItem()
        {
            InitializeComponent();
            RegisterChildrenObservation(); // <- here !
        }
    }
}

5)イニシャライザで呼び出したメソッド ハンドラを宣言することにより、BarStaticItem.Children.cs ファイルでChildren コレクションの動作を処理します。

これは単なる形式的な手順です。全体を理解すれば、xaml だけで行うよりも多くのシナリオを作成できることがわかります。まず、ここで重要なのは 2 つの状態だけです。

  • NotifyCollectionChangedAction.Add
  • NotifyCollectionChangedAction.Remove

    private void Children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
            {
                foreach (UIElement currentElement in e.NewItems)
                {
                    MyChildContainer.Children.Add(currentElement);
                }
                break;
            }
    
            case NotifyCollectionChangedAction.Move:
            {
                break;
            }
    
            case NotifyCollectionChangedAction.Remove:
            {
                foreach (UIElement currentElement in e.OldItems)
                {
                    MyChildContainer.Children.Remove(currentElement);
                }
                break;
            }
    
            case NotifyCollectionChangedAction.Replace:
            {
                break;
            }
    
            case NotifyCollectionChangedAction.Reset:
            {
                break;
            }
    
            default:
            {
                break;
            }
        }
    }
    

6) これでほぼ完了ですが、BarStaticItem.xaml ファイルで UIElement を作成して名前を付け、追加した UIElements を含める必要があります。

<UserControl ...>
    <Grid 
        x:Name="MyChildContainer"><!-- HERE ! -->
    </Grid>
</UserControl>

その後、完了し、XAML で BarStaticItem に任意の子要素を直接追加することができます。

<dxb:BarStaticItem>
    <TextBlock Text="{Binding MyStatusBarText}"></TextBlock>
</dxb:BarStaticItem>

..そして、それはで定義され、名前が付けられたTextBlockに着陸します。DockPanel または StackPanel を使用できます。子要素がそのタイプに基づいてどのコンテナーに移動するかを決定したり、場合によっては (依存関係) プロパティを更新したりできます。GridMyChildContainerBarStaticItem.xamlNotifyCollectionChangedAction.Add

private void Children_CollectionChanged(
    object sender, NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        case NotifyCollectionChangedAction.Add:
        {
            foreach (UIElement currentElement in e.NewItems)
            {
                if (currentElement.GetType() == typeof(TextBlock))
                {
                    TextBlock currentTextBlock = (TextBlock)currentElement;
                    // Manipulate your TextBlock...
                    HeaderTextBlockContainer.Children.Add(currentElement);
                }
                else if (currentElement.GetType() == typeof(Button))
                {
                    FooterButtonsDockPanel.Children.Add(currentElement);
                    DockPanel.SetDock(currentElement, Dock.Right);
                }
                else
                {
                    MainContentContainer.Children.Add(currentElement);
                }
                ContentDefined = true; // Custom Property.
            }
            //...

DV あなたは私じゃない

于 2015-01-18T07:29:08.107 に答える
0

この XAML は正常に動作しますが、制限があります (表示されるテキストの色を要求どおりに設定することはできません)。

<dxb:BarStaticItem
    Content="{Binding MyStatusBarText}">
</dxb:BarStaticItem> 

この特定のコントロールにより、ContentTemplate. これを使用して、コンテンツのスタイルを設定できます。

<dxb:BarStaticItem
   ContentTemplate="????">
</dxb:BarStaticItem>   

まず、 in を定義DataTemplateWindow.Resourcesます。これが私たちContentTemplateが指摘することです:

<Window.Resources>
    <DataTemplate x:Key="MyStatusBarContentTemplate">
        <!-- As the DataContext of a resource does not default to the window, we have to use RelativeSource to find the window. -->
        <TextBlock Name="MyText"                
            Text="{Binding Path=MyStatusBarText, 
            RelativeSource={RelativeSource Mode=FindAncestor,
            AncestorType=Window}}">                
        </TextBlock>
    </DataTemplate>
</Window.Resources>

DataContextDataTemplateXAML の残りの部分とは異なるため、XAML を省略するRelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}とバインディングが正しく機能しません。それ以外は、コントロールのコンテンツをレンダリングするために使用できるテンプレートを定義するだけです。

次に、コントロールを this に向けDataTemplateます。

<dxb:BarStaticItem
    ContentTemplate="{DynamicResource MyStatusBarContentTemplate}">
</dxb:BarStaticItem>

カスタム データ テンプレートを定義したので、やりたいことが何でもできます。たとえばConverter、ステータス バーにテキストが含まれている場合にテキストを赤く着色する を追加できますError(それ以外の場合は不可能でした)。

DataTemplateこの回答は、 を使用してほとんどのコントロールのカスタム コンテンツを表示する方法も示しています。

アップデート

Window のリソースで を定義するのではなく、DataTemplateのリソースとして定義しましたBarStaticItem。これにより、関連する項目が XAML にまとめられます。

この特定の XAML は、テキストに文字列が含まれている場合、ステータス バーのテキストが自動的に赤くErrorなり、ステータス バーのテキストに自動的に時間のプレフィックスが付けられることを意味します。コンバーターの C# コードを投稿してほしい場合はお知らせください。

<dxb:BarStaticItem
  ContentTemplate="{DynamicResource MyStatusBarContentTemplate}">
  <dxb:BarStaticItem.Resources>
      <DataTemplate x:Key="MyStatusBarContentTemplate">
          <!-- As the DataContext of a resource does not default to the window, we have to use RelativeSource to find the window. -->
          <TextBlock Name="MyText"
              Foreground="{Binding ElementName=MyText, Path=Text, Converter={StaticResource ColorRedIfTextContainsError}}"
              Text="{Binding Path=SettingsGlobalViewModel.StatusBarText, 
              RelativeSource={RelativeSource Mode=FindAncestor,
              AncestorType=Window},
              Converter={StaticResource PrefixStringWithTime}}">
          </TextBlock>
      </DataTemplate>
  </dxb:BarStaticItem.Resources>
</dxb:BarStaticItem> 
于 2015-01-17T14:45:41.320 に答える