-1

この質問が数え切れないほど聞かれていることは知っていますが、彼らの問題が何であるか、または彼らの例に従う方法の半分を理解していません. 私が彼女の名前を見つけたレイチェルは、それについてのブログを投稿しましたが、彼女の説明は簡単すぎました..

http://rachel53461.wordpress.com/2011/07/17/wpf-error-specified-element-is-already-the-logical-child-of-another-element-disconnect-it-first/

ここの例に従う前に私が持っていたものは次のとおりです。

<Window x:Class="Graph.View.MainView.Main"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:lc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol"
    Title="Main" Height="350" Width="525" 

    xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking">

<DockPanel LastChildFill="True">
       <DockPanel>
        <Label  Content="{Binding ScreenContent}" Grid.Row="1" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch"/>
        </DockPanel>
    </DockPanel>

ScreenContentは論理的な親を持っているため、再利用できません。レイチェルの例に従おうとした後:

<Window x:Class="Graph.View.MainView.Main"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:lc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol"
        Title="Main" Height="350" Width="525" 
       >
    <Window.Resources>
        <Style     TargetType="{x:Type ContentControl}">
            <Setter Property="ContentTemplate"> 
                <Setter.Value>
                    <DataTemplate>
                        <DockPanel>
                            <Label   Content="{Binding ScreenContent}" Grid.Row="1" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch"/>
                        </DockPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <DockPanel LastChildFill="True">            
        <Label Style="{StaticResource MyCustomContentControl}"/>
    </DockPanel>
</Window>

どうすれば修正できますか?何も表示されません...ありがとう。

4

3 に答える 3

1

ScreenContentプロパティとは何か答えてください...文字列ですか?またはいくつかのGUI要素?

文字列の場合は、以下の解決策に従ってください...

また、理解しなければならない概念がいくつかあります...

  1. Label内部Labelは悪いUIデザインです。
  2. ContentControlsなどLabelのおよびButtonを設定する場合は、特定の XAML パターンに従います。ControlTemplateDataTemplate
  3. あなたのケースでは、データ コンテキスト ベースのプロパティを割り当てたいと考えていますScreenContent。だからDataTemplate道は正しい。

ただし、外側(に適用したもの) が独自のプロパティに設定されていないため、これはLabel内側には流れません。DataTemplateLabelStyleContent

したがって、基本的には、ContentControl.ContentTemplatenull以外Contentが設定されている場合にのみ機能し、そのContentControl内部DataTemplate( ContentTemplate) はすべてのアイテムのようにContent機能します!DataContext

以下の表現に注意してください{Binding}... 自明です!!

    <DockPanel LastChildFill="True">
        <DockPanel.Resources>
            <Style x:Key="MyCustomContentControl"
                   TargetType="{x:Type ContentControl}">
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <DockPanel>
                                    <ContentPresenter
                                             Content="{Binding}"
                                             HorizontalAlignment="Stretch"
                                             VerticalAlignment="Stretch"/>
                                </DockPanel>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </DockPanel.Resources>
        <Label Style="{StaticResource MyCustomContentControl}"
               Content="{Binding ScreenContent}" 
               HorizontalContentAlignment="Stretch"
               VerticalContentAlignment="Stretch">
        </Label>
    </DockPanel>

それが UserControl の場合は、以下の解決策に従ってください...

(指定されたに)一度だけ割り当てていますLabelか?それとも、そのようなさまざまな要素のコンテンツとして割り当てようとしていますか?

一度だけ割り当てられた場合、上記の解決策が機能するはずです。

ただし、複数のターゲット要素として割り当てる予定の場合は、 /アプローチContentに従う必要があります。ModelViewModel

  1. すべての GUI 要素は XAML でホストする必要があります。
  2. コード ビハインドで GUI 要素を処理しないでください。
  3. コード ビハインドは、GUI 要素のソフトコピー、つまり GUI (UserControl) が表すフィールドに固有のデータに対してのみ機能します。

例えば

例 1...

タイトルのテキストを表示TitleControlする太字の斜体の WPF のような があるとします。タイトルテキストが設定されたオブジェクトが保持されていLabelますDataContextTitleControl

次に、ViewModelアプローチでは、のTitleControlViewModel 一部としてのインスタンスを作成する必要がありますDataContext...このようなもの...

YourDataContext.MyTitleControlViewModel = new TitleControlViewModel();

クラス内には、string 型TitleControlViewModelの public プロパティが必要です。MyTitle

YourDataContext.MyTitleControlViewModel.MyTitle = "My Title";

テンプレート固有の XAML は次のようになります...

    <DataTemplate x:Key="MyTitleControlDataTemplate">
         <local:TitleControl Title="{Binding MyTitle}"/>
    </DataTemplate>

ホストパネルは次のようになります...

    <ContentControl ToolTip="Title is shown here..." 
                    Content="{Binding MyTitleControlViewModel}"
                    Contenttemplate="{StatiocResource MyTitleControlDataTemplate}"/>

    <ContentControl ToolTip="Same title control is shown here also !!!"
                    Content="{Binding MyTitleControlViewModel}"
                    Contenttemplate="{StatiocResource MyTitleControlDataTemplate}"/>

このように、同じタイトル コントロールが上記の 2 つのコンテンツ コントロールでホストされているように見えます。しかし、よく考えてみると、TitleControl単に同じものを表しているだけで MyTitleControlViewModel、同じコントロールのように見える2 つの異なる例があります。

データ テンプレートと MVVM がどのように適合するかについては、Google を参照してください。

于 2012-06-27T09:23:25.647 に答える
0

再利用したい場合ScreenContent(すでに他の要素の子ですが)、最初にそれを複製し、複製されたコントロールを使用する必要があります。

最初にを使用してシリアル化することでコントロールのクローンを作成し、次に、を使用して逆シリアル化することでXamlWriter新しいコントロールを作成できますXamlReader

string screenContentXml = XamlWriter.Save(ScreenContent );

//Load it into a new object:
StringReader stringReader = new StringReader(screenContentXml );
XmlReader xmlReader = XmlReader.Create(stringReader);
UIElement screenContentClone = (UIElement)XamlReader.Load(xmlReader);

これscreenContentClone をウィンドウで使用します。

ただし、使用にはいくつかの制限があるためXamlWriter.Save(バインディングなど) 、回避策を適用して機能させることができます-XamlWriter.Saveのシリアル化の制限

シリアル化のための他のいくつかのアプローチがあります-

バインディングを保持するXAMLシリアライザー

XamlWriterとバインディングのシリアル化

AngelWPFが述べたようにデザインは正しく見えないので、ウィンドウを再デザインしてみてください。そうする必要はないかもしれません。

于 2012-06-27T09:45:35.617 に答える
0

UserControls(またはその他の種類の UI コントロール) は、ViewModel

DataTemplateバインドしているオブジェクトを用意し、 a を使用して WPF を使用してそのオブジェクトを描画する方法を指示する方がはるかに良いでしょうUserControl

たとえば、

ScreenModel ScreenContent { get; set; }

ScreenModelこのようなカスタムクラスはどこにありますか

public class ScreenModel
{
    public string Name { get; set; }
    ...
}

次に、次のようなものを使用してそれにバインドします。

<DockPanel LastChildFill="True">
    <DockPanel>
        <ContentControl Content="{Binding ScreenContent}" Grid.Row="1" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch"/>
    </DockPanel>
</DockPanel>

そして、クラスDataTemplateを描画する方法をWPFに伝えるために a を使用しますScreenModel

<DataTemplate DataType="{x:Type models:ScreenModel}">
    <views:ScreenContentUserControl />
</DataTemplate>

また

<DataTemplate DataType="{x:Type models:ScreenModel}">
    <Label Content="{Binding Name}" />
</DataTemplate>

を使用しているためTemplate、WPF は必要に応じて の新しいコピーを作成し、複数の場所UserControlで同じものを使用しようとしません。UserControl

バインディングを介して同じUserControl( ScreenContent) をVisualTree複数回追加しているため、エラーが発生しています。Content="{Binding ScreenContent}"

タブを切り替えるようなことをしても、おそらくこのエラーが発生します。これは、タブから切り替えてすべての UI オブジェクトをアンロードし、元に戻すことで新しい UI オブジェクトをロードするScreenContentためです。もはや存在しない。

于 2012-06-27T12:04:42.260 に答える