Calender

S M T W T F S
   1234
567891011
12131415161718
19202122232425
262728293031 
<< August 2018 >>

Categories

Archives

Recent Entries

Recent Comment

Recent Trackback

w closet×JUGEM

-

UserControl間でお互いを知らずにデータのやり取りをしたい

@media print { body { margin: 2mm 9mm; } .original-url { display: none; } #article .float.left { float: left !important; } #article .float.right { float: right !important; } #article .float { margin-top: 0 !important; margin-bottom: 0 !important; } } UserControl間でお互いを知らずにデータのやり取りをしたい

UserControl間でお互いを知らずにデータのやり取りをしたい

方法1

ユーザーコントロールAのプロパティAとユーザーコントロールBのプロパティBの両方を添付プロパティにして、プロパティBにコントロールAをバインディングする。
そのプロパティがUI用のプロパティでModelとは関係ない場合はこちらでもいい。

方法2
ViewModeかModelで両方のプロパティの値を持たせて、値変更時にもう一方のプロパティも変更するように作る。
UI用ではなくModelとして関連しているのであればこちらを推奨します。というか、こうなるはず。

<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="200" Width="200">
    <StackPanel >
        <!-- 方法1 ModelかViewModeにプロパティA,Bを持たせる方法-->
        <StackPanel  Margin="0,10,0,0" x:Name="sAB">
            <local:UserControlA x:Name="ucA1" Text="{Binding Path=A}"/>
            <local:UserControlB x:Name="ucB1" Text="{Binding Path=B}"/>
        </StackPanel>

        <!-- 方法2 お互いに添付プロパティを公開してバインディングする方法-->
        <StackPanel  Margin="0,10,0,0" x:Name="sA">
            <local:UserControlA x:Name="ucA0" Text="{Binding Path=A}" />
            <local:UserControlB x:Name="ucB0" Text="{Binding Path=Text,ElementName=ucA0 }"/>
        </StackPanel>
    </StackPanel>
</Window>
<UserControl x:Class="WpfApplication1.UserControlA" 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="50" d:DesignWidth="100"
             x:Name="uc">
    <Grid>
        <TextBox Text="{Binding Path=Text,ElementName=uc,UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</UserControl>
<UserControl x:Class="WpfApplication1.UserControlB"  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="50" d:DesignWidth="100"
             x:Name="uc">
    <Grid>
        <TextBox Text="{Binding Path=Text,ElementName=uc,UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</UserControl>
C#版
using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.sA.DataContext = new ViewModelA();

            this.sAB.DataContext = new ViewModelAB();
        }
    }

    class ViewModelBase : System.ComponentModel.INotifyPropertyChanged
    {
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string name)
        {
            var pc = PropertyChanged;
            if (pc != null)
            {
                pc(this, new System.ComponentModel.PropertyChangedEventArgs(name));
            }
        }
    }

    /// <summary>ユーザーコントロールAのみに設定するViewModel</summary>
    class ViewModelA : ViewModelBase
    {
        public virtual string A
        {
            get { return _A; }
            set
            {
                if (_A != value)
                {
                    _A = value;
                    OnPropertyChanged("A");
                }
            }
        }
        private string _A;
    }

    /// <summary>ユーザーコントロールAとBの両方のViewModelとする</summary>
    class ViewModelAB : ViewModelA
    {
        public override string A
        {
            get { return _A; }
            set
            {
                base.A = value;
                B = value;
            }
        }
        private string _A;

        public string B
        {
            get { return _B; }
            set
            {
                if (_B != value)
                {
                    _B = value;
                    A = value;
                    OnPropertyChanged("B");
                }
            }
        }
        private string _B;
    }

    /// <summary>添付プロパティとしてTextを定義してあるユーザーコントロールA</summary>
    public partial class UserControlA : UserControl
    {
        public UserControlA()
        {
            InitializeComponent();
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register
            ("Text"
            , typeof(string)
            , typeof(UserControlA)
            , new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    }

    /// <summary>添付プロパティとしてTextを定義してあるユーザーコントロールB</summary>
    public partial class UserControlB : UserControl
    {
        public UserControlB()
        {
            InitializeComponent();
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register
            ("Text"
            , typeof(string)
            , typeof(UserControlB)
            , new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    }
}
VB.net
Imports System.ComponentModel

Class MainWindow
    Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        Me.sA.DataContext = New ViewModelA()

        Me.sAB.DataContext = New ViewModelAB()
    End Sub
End Class

Class ViewModelBase
    Implements System.ComponentModel.INotifyPropertyChanged

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged

    Protected Overridable Sub OnPropertyChanged(ByVal name As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
    End Sub
End Class


''' <summary>ユーザーコントロールAのみに設定するViewModel</summary>
Class ViewModelA
    Inherits ViewModelBase

    Private _A As String

    Public Overridable Property A() As String
        Get
            Return Me._A
        End Get
        Set(value As String)
            If Me._A <> value Then
                Me._A = value
                Me.OnPropertyChanged("A")
            End If
        End Set
    End Property
End Class

''' <summary>ユーザーコントロールAとBの両方のViewModelとする</summary>
Class ViewModelAB
    Inherits ViewModelA

    Private _A As String
    Private _B As String

    Public Overrides Property A() As String
        Get
            Return Me._A
        End Get
        Set(value As String)
            MyBase.A = value
            Me.B = value
        End Set
    End Property

    Public Property B() As String
        Get
            Return Me._B
        End Get
        Set(value As String)
            If Me._B <> value Then
                Me._B = value
                Me.A = value
                Me.OnPropertyChanged("B")
            End If
        End Set
    End Property
End Class

''' <summary>添付プロパティとしてTextを定義してあるユーザーコントロールA</summary>
Partial Public Class UserControlA
    Inherits UserControl

    Public Sub New()
        InitializeComponent()
    End Sub

    Public Property Text() As String
        Get
            Return CStr(MyBase.GetValue(UserControlA.TextProperty))
        End Get
        Set(value As String)
            MyBase.SetValue(UserControlA.TextProperty, value)
        End Set
    End Property

    Public Shared ReadOnly TextProperty As DependencyProperty _
         = DependencyProperty.Register _
            ("Text", GetType(String), GetType(UserControlA) _
            , New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault))
End Class

''' <summary>添付プロパティとしてTextを定義してあるユーザーコントロールB</summary>
Partial Public Class UserControlB
    Inherits UserControl

    Public Sub New()
        InitializeComponent()
    End Sub

    Public Property Text() As String
        Get
            Return CStr(MyBase.GetValue(UserControlA.TextProperty))
        End Get
        Set(value As String)
            MyBase.SetValue(UserControlA.TextProperty, value)
        End Set
    End Property

    Public Shared ReadOnly TextProperty As DependencyProperty _
         = DependencyProperty.Register _
            ("Text", GetType(String), GetType(UserControlB) _
            , New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault))
End Class


個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)



iPadから送信
  • 2018.08.06 Monday
  • 10:26

Comment
Send Comment








   
この記事のトラックバックURL
Trackback