1

について学んでいDependency Propertiesます。

内に を作成しDependency PropertyUserControl内にMainWindowコントロールのインスタンスを作成して値を設定します。これは期待どおりに機能します。

私の問題は、使用しようとするときBindingです。

したがって、私の MainWindow XAML は次のようになります (StartTime 型は文字列です)

<Window x:Class="TimeLineCanvas.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:timeline="clr-namespace:TimeLineCanvas.UserControls"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <TextBlock Text="{Binding StartTime}" Height="100" /><!--Works binding to local property-->
            <timeline:TimeLine StartTime="28/01/2015" Height="100" /><!--Works when hard coded value-->
            <timeline:TimeLine StartTime="{Binding StartTime, UpdateSourceTrigger=PropertyChanged}" Height="100" /><!-- Does not display anything -->            
             <timeline:TimeLine x:Name="TimeLineInXaml" Height="100" /><!-- Works (value set in code behind) -->            
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Windows;
using System.ComponentModel;

namespace TimeLineCanvas
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        #region Constructors

        public MainWindow()
        {
            InitializeComponent();
            SetStartTime(DateTime.Now);
            TimeLineInXaml.StartTime = _startTime; 
            this.DataContext = this;
        }

        #endregion

        #region Properties

        private string _startTime;
        public string StartTime
        {
            get
            {
                return _startTime;
            }
            set
            {
                _startTime = value;
                OnPropertyChanged("StartTime");
            }
        }

        #endregion

        #region Methods

        internal void SetStartTime(DateTime dt)
        {
            this.StartTime = dt.ToShortDateString();
        }

        #endregion

        #region INotifyPropertyChanged Implementation

        public void OnPropertyChanged(string PropertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion INotify
    }
}

私のユーザーコントロール

<UserControl x:Class="TimeLineCanvas.UserControls.TimeLine"
             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>
        <Canvas>
            <TextBlock Text="{Binding StartTime, UpdateSourceTrigger=PropertyChanged}" />
        </Canvas>           
    </Grid>
</UserControl>

および私の UserControl の背後にあるコード

using System;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;

namespace TimeLineCanvas.UserControls
{
    /// <summary>
    /// Interaction logic for TimeLine.xaml
    /// </summary>
    public partial class TimeLine : UserControl, INotifyPropertyChanged
    {
        #region Constructor

        public TimeLine()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        #endregion

        #region Dependancy Properties

        public static readonly DependencyProperty StartTimeProperty = DependencyProperty.Register(
            "StartTime",
            typeof(string),
            typeof(TimeLine));

        #endregion

        #region Properties

        public string StartTime
        {
            get { return (string)GetValue(TimeLine.StartTimeProperty); }
            set
            {
                DateTime result;
                if (!DateTime.TryParse(value, out result))
                    System.Diagnostics.Debug.Assert(false, "Expected a value which can be converted to a DateTime");

                SetValue(TimeLine.StartTimeProperty, value);
            }
        }

        #endregion


        #region INotifyPropertyChanged Implementation

        public void OnPropertyChanged(string PropertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion INotify
    }
}

だから、問題は明らかです。それはバインディングですが、これを解決する方法がわかりません! DataContext="{Binding RelativeSource={RelativeSource Self}}他の提案 ( UserControl への追加、MainWindow と UserContorl の両方への INotifyPropertyChanged の追加など) に基づく私の Voodoo プログラミング (すべてをランダムな順序で試す) でさえ、結果には影響しません。

私は何を間違っていますか、それとも意図していないことをしようとしていますか?

4

2 に答える 2

1

バインディングの理解を単純化する必要があるだけです。ここには 2 ロットのバインディングがあることを覚えておいてください

MainWindow はプロパティ StartTime を使用して INotify を実装します TimeLine ユーザー コントロールには DP StartTime があります

そのため、MainWindow は MainWindow.cs のプロパティ StartTime にバインドされています NB Button で時刻の変更をテストします

<Grid>
    <StackPanel>          
        <timeline:TimeLine x:Name="myTime" StartTime="{Binding StartTime, Mode=TwoWay}" Height="100" /> 
        <Button Content="Change Time"  Width="200" Height="100" Click="Button_Click"/>                 
    </StackPanel>
</Grid>

メインウィンドウのバックエンド

public partial class MainWindow : Window, INotifyPropertyChanged
{
    #region Constructors

    public MainWindow()
    {
        InitializeComponent();           
        this.DataContext = this;
            Loaded += (s, args) =>
            {
                this.myTime.StartTime = "Some Time";
            };
    }

    #endregion

    #region Properties

    private string _startTime;
    public string StartTime
    {
        get
        {
            return _startTime;
        }
        set
        {
            _startTime = value;
            OnPropertyChanged("StartTime");
        }
    }

    #endregion       

    #region INotifyPropertyChanged Implementation

    public void OnPropertyChanged(string PropertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion INotify

     private void Button_Click(object sender, RoutedEventArgs e)
     {
        // We are changing usercontrol StartTime DP which updates or property in main             //window
        this.myTime.StartTime = "A new TIME";
     }
}

}

UserControl (バックエンドで DP にバインド)

<Grid>
    <Canvas>
        <TextBlock Text="{Binding StartTime}" />
    </Canvas>           
</Grid>

UserControl バックエンドには DP しかありません

public partial class TimeLine : UserControl
{
    #region Constructor

    public TimeLine()
    {
        InitializeComponent();           
    }

    public string StartTime
    {
        get { return (string)GetValue(StartTimeProperty); }
        set { SetValue(StartTimeProperty, value); }
    }

    // Using a DependencyProperty as the backing store for StartTime.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty StartTimeProperty =
        DependencyProperty.Register("StartTime", typeof(string), typeof(TimeLine), new PropertyMetadata(""));
}

Change Time ボタンをクリックすると、ユーザーコントロールが MainWindow プロパティを更新します。それが役立つことを願っています

于 2013-11-05T12:24:52.003 に答える
0

プロパティ名が重複しており、「Voodoo プログラミング」中に明らかに多くのテストを行ったため、コードは少し混乱しています。:)

しかし、とにかくあなたの問題を見つけたと思います。TimeLineクラスで次の行を削除してみてください。

this.DataContext = this;

これはコントロールではなく、MainWindow.

説明:

MainWindow コンストラクターでは、MainWindowDataContextをそれ自体に設定します。DataContext明示的に設定されていない場合、子要素は親要素から継承します。したがって、 のDataContextTextBlockMainWindow に設定されているため、Bindingここでは が適切に機能します。ただし、すべてのTimeLineインスタンスで、DataContext明示的に (コンストラクターで) 自分自身、つまりTimeLineオブジェクトに設定します。このようにBindingTimeLineインスタンスの はMainWindowStartTimeプロパティを参照するのではなく、TimeLineコントロール内の同じ名前のプロパティを参照します。ただし、このプロパティは実際の値に設定されることはありません (それ自体にバインドされるだけで意味がありません)。したがって、何も表示されません。

于 2013-11-05T13:15:29.003 に答える