2

概要:

UserControlとという名前の2 つの がZoneありZoneGroupます。これらのコントロールの 1 つ ( )ZoneGroupには、もう 1 つのコントロールの 2 つのインスタンス ( ) が含まれていますZone。どちらも、イベント ハンドラでDataContextルート要素をthis, に設定します。Loaded

問題は、読み込み前DataContextに内部コントロール ( s) が設定されている (イベントが の前に発生した) ため、UI で誤動作が発生することです。(内部コントロールの初期状態が間違っています。) それを防ぐと、次のエラー レポートが表示されることを除いて、すべて正常に動作します (少なくとも正常に動作するようです!)。(出力ウィンドウで)ZoneDataContextChangedLoadedZone

public partial class Zone : UserControl
{
    ∙∙∙

    private void Zone_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        // Adding this if-clause solve UI problems but makes some binding errors!
        if (this.IsLoaded)
            brdRoot.DataContext = this;
    }
}

System.Windows.Data エラー: 40: BindingExpression パス エラー: 'ZoneBrush' プロパティが 'object' ''ZoneGroup' (Name='')' に見つかりません。BindingExpression:Path=ZoneBrush; DataItem='ZoneGroup' (Name=''); ターゲット要素は 'brdRoot' (Name='') です。ターゲット プロパティは 'BorderBrush' (タイプ 'Brush') です

詳細:

そのようないくつかのデータバインディングを含むUserControl名前があります..Zone

<UserControl x:Class="MyApp.Zone"
    ∙∙∙&gt;
    <Border x:Name="brdRoot" BorderBrush="{Binding ZoneBrush}" BorderThickness="1">
        ∙∙∙
    </Border>
</UserControl>

したがって、brdRootデータコンテキストを次のように設定します

public partial class Zone : UserControl
{
    public Brush ZoneBrush
    {
        get { return (Brush)GetValue(ZoneBrushProperty); }
        set { SetValue(ZoneBrushProperty, value); }
    }

    ∙∙∙

    public Zone()
    {
        InitializeComponent();
    }

    private void Zone_Loaded(object sender, RoutedEventArgs e)
    {
        brdRoot.DataContext = this;
    }

    ∙∙∙
}

また、2 つのコントロールを格納して管理するためにUserControl2 つの があるものもあります。ContentPresenterZone

<UserControl x:Class="MyApp.ZoneGroup"
    ∙∙∙&gt;
    <Border x:Name="brdRoot" BorderBrush="Gray" BorderThickness="1">
        <StackPanel Orientation="Horizontal">
            <ContentPresenter Content="{Binding MainZone}"
                              Margin="{Binding MainZonePadding}"/>
            <ContentPresenter Content="{Binding MemberZone}"/>
        </StackPanel>
    </Border>
</UserControl>

コードビハインドは次のとおりです。

public partial class ZoneGroup : UserControl
{
    public Thickness MainZonePadding
    {
        get { return (Thickness)GetValue(MainZonePaddingProperty); }
        set { SetValue(MainZonePaddingProperty, value); }
    }

    public Zone MainZone
    {
        get { return (Zone)GetValue(MainZoneProperty); }
        set { SetValue(MainZoneProperty, value); }
    }

    public Zone MemberZone
    {
        get { return (Zone)GetValue(MemberZoneProperty); }
        set { SetValue(MemberZoneProperty, value); }
    }


    public ZoneGroup()
    {
        InitializeComponent();
    }

    private void ZoneGroup_Loaded(object sender, RoutedEventArgs e)
    {
        brdRoot.DataContext = this;
    }

    ∙∙∙
}

編集 ►スケッチ: ゾーン グループ コントロール内の 2 つのゾーン コントロール。

アプリは期待どおりに正常に動作しますが、一部の BindingExpression エラーが報告されます。

4

2 に答える 2

1

これは直接的な答えではありません!

@HighCore が言ったように、ユーザー コントロールにItemsControl2 つの s を実装する代わりに、 an を使用しようとしました。ContentPresenterわかりやすくするために、簡単に説明できるように新しいシンプルなアプリを作成しました。したがって、いくつかの新しい仮定を検討してください。

ここでも、 が 2 つありUserControlます。MyItemおよびMyItemsControl次のとおりです。

<UserControl x:Class="MyApp.MyItem"
             ∙∙∙&gt;
    <Grid x:Name="grdRoot">
        <Border BorderBrush="{Binding ItemBorderBrsuh}" BorderThickness="1">
            <TextBlock x:Name="txtColorIndicator"
                       Text="Item"
                       TextAlignment="Center"
                       Margin="5"/>
        </Border>
    </Grid>
</UserControl>

C# コード ビハインド:

public partial class MyItem : UserControl
{
    #region ________________________________________  ItemBorderBrsuh

    public Brush ItemBorderBrsuh
    {
        get { return (Brush)GetValue(ItemBorderBrsuhProperty); }
        set { SetValue(ItemBorderBrsuhProperty, value); }
    }

    public static readonly DependencyProperty ItemBorderBrsuhProperty =
        DependencyProperty.Register("ItemBorderBrsuh",
                                    typeof(Brush),
                                    typeof(MyItem),
                                    new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Black), FrameworkPropertyMetadataOptions.None, OnItemBorderBrsuhPropertyChanged));

    private static void OnItemBorderBrsuhPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        MyItem instance = sender as MyItem;

        if (instance != null && e.NewValue is SolidColorBrush)
            instance.txtColorIndicator.Text = (e.NewValue as SolidColorBrush).Color.ToString();
    }

    #endregion

    public MyItem()
    {
        InitializeComponent();

        grdRoot.DataContext = this;
    }
}

これが MyItemsControl です。

<UserControl x:Class="MyApp.MyItemsControl"
    ∙∙∙&gt;
    <StackPanel>
        <TextBlock x:Name="txtHeader" Margin="0,0,0,5" TextAlignment="Center" Text="0 Item(s)"/>
        <Border BorderBrush="Gray" BorderThickness="1" Padding="5">
            <ItemsControl x:Name="itemsControl" ItemsSource="{Binding Items}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <local:MyItem />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Border>
    </StackPanel>
</UserControl>

C# コード ビハインド:

public partial class MyItemsControl : UserControl
{
    private ObservableCollection<MyItem> _Items = new ObservableCollection<MyItem>();
    public ObservableCollection<MyItem> Items
    {
        get
        {
            return _Items;
        }
        set
        {
            _Items = value;
        }
    }

    private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        txtHeader.Text = Items.Count + " Item(s)";
    }

    public MyItemsControl()
    {
        InitializeComponent();
        Items.CollectionChanged += Items_CollectionChanged;

        this.DataContext = this;
    }
}

MyItem内での使用方法は次のとおりMyItemsControlです。

<Grid>
    <local:MyItemsControl HorizontalAlignment="Center" VerticalAlignment="Center" Padding="5" BorderBrush="Black" BorderThickness="1">
        <local:MyItemsControl.Items>
            <local:MyItem ItemBorderBrsuh="Green" Margin="1"/>
            <local:MyItem ItemBorderBrsuh="Red" Margin="1"/>
            <local:MyItem ItemBorderBrsuh="Blue" Margin="1"/>
            <local:MyItem ItemBorderBrsuh="Orange" Margin="1"/>
        </local:MyItemsControl.Items>
    </local:MyItemsControl>
</Grid>

さて、s には問題はありませんBindingExpressionが、重要な疑問が残ります。交換方法

{
    grdRoot.DataContext = this;
}

{
    this.DataContext = this;
}

真のViewModel

スクリーンショット:

MyItems コントロール


編集: MVVM パターンを実装しようとしましたが、いくつかの問題があります。私はここで最初のものを尋ねまし。

于 2013-03-29T08:27:59.727 に答える