开发者

With WPF DataBinding how do I have multiple clients for single source?

开发者 https://www.devze.com 2022-12-20 16:55 出处:网络
I have a data class that implements INotifyPropertyChanged and two WPF controls that DataBind to the same value. Only one WPF control is updated, why?

I have a data class that implements INotifyPropertyChanged and two WPF controls that DataBind to the same value. Only one WPF control is updated, why?

Here is my data class:

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

namespace TestMultiBind
{
    class DataSource : INotifyPropertyChanged
    {
        static int _DataValue;
        static DispatcherTimer tmr = new DispatcherTimer();
        static int _ClientCount = 0;

        #region InotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        public int DataValue
        {
            get { return _DataValue; }
        }

        public DataSource()
        {
            if (!DesignerProperties.GetIsInDesignMode(new System.Windows.DependencyObject()))
            {
                _ClientCount = _ClientCount + 1;
                if (!tmr.IsEnabled)
                {
                    tmr.Interval = TimeSpan.FromMilliseconds(10);
                    tmr.Tick += new EventHandler(tmr_Tick);
                    tmr.Start();
                }
            }
        }
        void tmr_Tick(object sender, EventArgs e)
        {
            _DataValue = DateTime.Now.Second;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("DataValue"));
            }
        }
    }

}

and here is my XAML

Title="Window1" Height="300" Width="300">
<Grid>
    <StackPanel>
        <ProgressBar Height="20"  Name="progressBar1" Value="{Binding Mode=OneWay, Path=DataValue}" Maximum="60">
            <ProgressBar.DataContext>
                <ds:DataSource/>
            </ProgressBar.DataContext>
        </ProgressBar>
        <ProgressBar Height="30"  Name="progressBar2" Value="{Binding Mode=OneWay, Path=DataValue}" Maximum="60">
            <ProgressBar.DataContext>
                <ds:DataSource/>
            </ProgressBar.DataContext>
        </ProgressBar>
    </StackPanel>
</Grid>

I have tried to present the simplest example possible, thus I created a data class that uses a timer to update a value once per second. The real world problem I am trying to solve is data coming across a serial port that is to be displayed. Thus开发者_StackOverflow I need to store static data for the incoming data within the class as well as handling instance specific events for each of the clients (WPF controls) that are data bound to the control.

It would appear that my tmr_Tick routine is somehow instance specific to the first client as opposed to being static to the class and raising the multiple events required for each of the clients.

What am I missing here or doing wrong?


I'm not sure if this is the best way to do this, but it works. The problem with my initial code was that I needed both a static and a instance constructor for the class. The timer is created in the static constructor (which is only run once) while there needs to be one event handler per binding so this is handled in the instance constructor.

Here is the code that works:

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

namespace TestMultiBind
{
    class DataSource : INotifyPropertyChanged
    {
        static int _DataValue;
        static DispatcherTimer tmr = new DispatcherTimer();

        #region InotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        public int DataValue
        {
            get { return _DataValue; }
        }

        static DataSource()
        {
            if (!DesignerProperties.GetIsInDesignMode(new System.Windows.DependencyObject()))
            {
                tmr.Interval = TimeSpan.FromMilliseconds(10);
                tmr.Start();
            }
        }
        public DataSource()
        {
            if (!DesignerProperties.GetIsInDesignMode(new System.Windows.DependencyObject()))
            {
                tmr.Tick += new EventHandler(tmr_Tick);
            }
        }
        void tmr_Tick(object sender, EventArgs e)
        {
            _DataValue = DateTime.Now.Second;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("DataValue"));
            }
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号