1

私はWPFにかなり慣れていないので(現在3週間使用しています)、愚かなことを見逃しているか、自分が何をしているのか理解していない可能性があります!

アプリケーション全体または現在のコントロールのいずれかをカバーするモーダルタイプのポップアップウィンドウを作成しようとしています。このコントロールを半透明にして、ユーザーが背後のコンテンツを見ることができるが使用できないようにします。その後、続行する前に、モーダル ウィンドウにあるものをすべて完了することができます。

さまざまな場所でコードを繰り返す必要がないため、私の目標は、XAML で使用でき、毎回必要なコンテンツを追加するだけで済む汎用コントロールを用意することです。つまり、フェード、透明度、背景色のエクストラはすべて 1 か所で処理され、そのインスタンスに特定の機能を追加するだけで済みます。

これまでのところ、jonblind というユーザー コントロールを作成しました。

<UserControl x:Class="ShapInteractiveClient.View.SampleTests.jonblind"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">


<Grid x:Name="blindGrid" Grid.RowSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
      Opacity="0.82">
    <Grid.Background>
        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0" MappingMode="RelativeToBoundingBox">
            <GradientStop Color="#FFA8CBFE" Offset="1"/>
            <GradientStop Color="Red"/>
            <GradientStop Color="#FFE1EDFE" Offset="0.147"/>
        </LinearGradientBrush>
    </Grid.Background>

    <ContentControl x:Name="contentTemplateArea" />

</Grid>

</UserControl>

次のように、コントロールのコードビハインドがあります。

public partial class jonblind : UserControl
{
    public jonblind()
    {
        InitializeComponent();
        SetVisibility(this);
    }

    [Category("jonblind")]
    public bool IsContentVisible
    {
        get { return (bool)GetValue(IsContentVisibleProperty); }
        set { SetValue(IsContentVisibleProperty, value); }
    }

    public static readonly DependencyProperty IsContentVisibleProperty = DependencyProperty.Register("IsContentVisible", typeof(bool), typeof(jonblind),
        new FrameworkPropertyMetadata(new PropertyChangedCallback(OnIsOverlayContentVisibleChanged)));

    private static void OnIsOverlayContentVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        jonblind blind = d as jonblind;
        if(blind != null)
            SetVisibility(blind);
    }

    private static void SetVisibility(jonblind blind)
    {
        blind.blindGrid.Visibility = blind.IsContentVisible ? Visibility.Visible : Visibility.Hidden;
    }



    [Category("jonblind")]
    public ContentControl ContentAreaControl
    {
        get { return (ContentControl)GetValue(ContentAreaControlProperty); }
        set { SetValue(ContentAreaControlProperty, value); }
    }

    public static readonly DependencyProperty ContentAreaControlProperty = DependencyProperty.Register("ContentAreaControl", typeof(ContentControl), typeof(jonblind),
        new FrameworkPropertyMetadata(new PropertyChangedCallback(OnContentAreaControlChanged)));

    private static void OnContentAreaControlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        jonblind blind = d as jonblind;
        if (blind != null && e.NewValue != null && e.NewValue is ContentControl)
        {
            blind.contentTemplateArea = e.NewValue as ContentControl;
        }
    }
}

次のように、別のユーザーコントロールに追加できます。

<UserControl.Resources>
<ContentControl x:Key="testcontrol">
        <StackPanel>
            <TextBox VerticalAlignment="Center" HorizontalAlignment="Center" Text="Loading!!!" />
            <Button Content="hide me!" Command="{Binding Path=alternateblind}" />
        </StackPanel>
    </ContentControl>
</UserControl.Resources>

<SampleTests:jonblind IsContentVisible="{Binding Path=ShowBlind}" ContentAreaControl="{StaticResource testcontrol}" />

「OnContentAreaControlChanged」にブレークポイントを設定すると、新しいコンテンツが渡されていることがわかりますが、実行時に表示されません。

これがすべて間違っているのか、それが可能かどうか、または微調整が必​​要なだけかどうかはわかりません。これに関するすべてのアドバイスと、この種のシナリオへの対処は大歓迎です。

4

3 に答える 3

2

これは問題に対する直接的な答えではありませんが、依存関係プロパティを使用する代わりに、コンテンツをコントロール内に配置する必要があります。UserControl を使用する代わりに、ContentControl を拡張するクラスを作成します。

public class jonblind : ContentControl
{
    [Category("jonblind")]
    public bool IsContentVisible
    {
        get { return (bool)GetValue(IsContentVisibleProperty); }
        set { SetValue(IsContentVisibleProperty, value); }
    }

    public static readonly DependencyProperty IsContentVisibleProperty = DependencyProperty.Register("IsContentVisible", typeof(bool), typeof(jonblind),
        new FrameworkPropertyMetadata(new PropertyChangedCallback(OnIsOverlayContentVisibleChanged)));

    private static void OnIsOverlayContentVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        jonblind blind = d as jonblind;
        if(blind != null)
            SetVisibility(blind);
    }

    private static void SetVisibility(jonblind blind)
    {
        blind.blindGrid.Visibility = blind.IsContentVisible ? Visibility.Visible : Visibility.Hidden;
    }
}

次に、スタイルを使用してコンテンツを指定します

<Style TargetType="control:jonblind">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="control:jonblind">
                <Grid>
                    <Grid.Background>
                        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0" MappingMode="RelativeToBoundingBox">
                            <GradientStop Color="#FFA8CBFE" Offset="1"/>
                            <GradientStop Color="Red"/>
                            <GradientStop Color="#FFE1EDFE" Offset="0.147"/>
                        </LinearGradientBrush>
                     </Grid.Background>
                    <ContentControl Content="{TemplateBinding Content}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

そして最後に - それを使用してください

<control:jonblind IsContentVisible="{Binding Path=ShowBlind}">            
    <StackPanel>
        <TextBox VerticalAlignment="Center" HorizontalAlignment="Center" Text="Loading!!!" />
        <Button Content="hide me!" Command="{Binding Path=alternateblind}" />
    </StackPanel>
</control:jonblind>

(このスレッドの例: How to create a WPF UserControl with NAMED content )

于 2011-03-24T17:40:55.330 に答える
1

これはWPFの一般的なパターンであり、ContentControl(1つの子コンテンツ)、HeaderedContentControl(2つの子コンテンツ)、またはItemsControl(n個の子のコレクション)から派生した多くの組み込みコントロールで使用されます。一般に、Contentプロパティ(実行時にプレースホルダーに置き換えられるもの)は、オブジェクト型である必要があります。また、変更ハンドラーを取り除き、この状況ではデータバインディングに依存することもできます。

[Category("jonblind")]
public object ContentAreaControl
{
    get { return GetValue(ContentAreaControlProperty); }
    set { SetValue(ContentAreaControlProperty, value); }
}

public static readonly DependencyProperty ContentAreaControlProperty = 
    DependencyProperty.Register("ContentAreaControl", typeof(object), typeof(jonblind),
    new FrameworkPropertyMetadata(null));

この新しいContentプロパティを使用すると、ContentPresenterを使用してバインディングを設定できます。これは、渡されるコンテンツのプレースホルダーとして機能します。これは、ContentPresenterをに接続できるContentControlから派生したカスタムコントロールでさらに簡単に設定できます。 ControlTemplate内のコンテンツ。

<UserControl x:Class="ShapInteractiveClient.View.SampleTests.jonblind"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

<Grid x:Name="blindGrid" Grid.RowSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
      Opacity="0.82">
    <Grid.Background>
        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0" MappingMode="RelativeToBoundingBox">
            <GradientStop Color="#FFA8CBFE" Offset="1"/>
            <GradientStop Color="Red"/>
            <GradientStop Color="#FFE1EDFE" Offset="0.147"/>
        </LinearGradientBrush>
    </Grid.Background>

    <ContentPresenter Content="{Binding Path=ContentAreaContent, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" />

</Grid>
</UserControl>

一般に、UIElementインスタンスをリソースとして宣言することはお勧めできません(代わりにテンプレートリソース内に配置することをお勧めします)が、これを他のコントロールと同じように扱うことで、この問題を簡単に回避できます。その場合、使用法はContentControl(Buttonなど)がどのように見えるかに非常に似ています。

<SampleTests:jonblind IsContentVisible="{Binding Path=ShowBlind}">
    <SampleTests:jonblind.ContentAreaControl>
        <StackPanel>
            <TextBox VerticalAlignment="Center" HorizontalAlignment="Center" Text="Loading!!!" />
            <Button Content="hide me!" Command="{Binding Path=alternateblind}" />
        </StackPanel>
    </SampleTests:jonblind.ContentAreaControl>
</SampleTests:jonblind>

UserControlではなくカスタムContentControlとしてこれを行うことで、さらに多くの利点を得ることができますが、複雑さが増し、概念をよりよく理解することは、一般に、正しく機能させるのに役立ちます。UserControlを使い始めている間は、必要なことを簡単に実行できます。

于 2011-03-24T20:32:18.057 に答える