WPF Change data context on the fly

Hi,

problem:
Let's say I have trying to render the same wpf window and pass different data context one after the other for example a counter.

For example:

Window that shows counter.
I need to see the counter increment 1, then 2

var counter = new Counter(1);
DataContext = counter;
//force update & refresh

counter = new Counter(2);
DataContext = counter;
//force update & refresh

I'm new to WPF how can I do it? Do I need depency? or to fire and event?

Please submit full sample.
breezbackAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ioannis ParaskevopoulosCommented:
I don't know if i get your question right, but take a look at the following example:

XAML
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="152" Width="124">
    <Grid>
        <TextBlock Height="23" HorizontalAlignment="Left" Margin="13,16,0,0" Name="textBlock1" Text="{Binding Path=Value, Mode=TwoWay}" VerticalAlignment="Top" />
        <Button Content="Count" Height="23" HorizontalAlignment="Left" Margin="12,45,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click"/>
        <Button Content="Reset" Height="23" HorizontalAlignment="Left" Margin="13,78,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click"/>
    </Grid>
</Window>

Open in new window


Code Behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        Counter _counter;

        public MainWindow()
        {
            InitializeComponent();
            _counter = new Counter();

            DataContext = _counter;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            _counter.Value ++;
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            _counter = new Counter();
            DataContext = _counter;
        }

        public class Counter : INotifyPropertyChanged
        {
            private int _Value;
            public int Value
            {
                get
                {
                    return _Value;
                }
                set
                {
                    _Value = value;
                    RaisePropertyChanged("Value");
                }
            }

            public Counter()
            {
                Value = 0;
            }
            public Counter(int value)
            {
                Value = value;
            }

            public event PropertyChangedEventHandler PropertyChanged;
            private void RaisePropertyChanged(string caller = "")
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(caller));
                }
            }


        }

    }
}

Open in new window


Things to notice here:

1.

The Counter class is implementing the INotificationPropertyChanged Interface, so it notifies when the property is changed. In VS 2012 things are a bit simpler, but in VS 2010 that i am using this is how you implement this. The bad thing is that you cannot use the simple version of getter setter of the properties.

2.

I am holding the instance of the class in a global variable and add this variable to the DataContext.

3.

When i click the Reset button i create a new Counter class and pass it to the DataContext.

4.

In XAML if you see, i bind the Text property of the TextBlock with a TwoWay mode binding.

This is a simple way of doing this.

There is a way of doing it using Dependency. Please refer to:



Disclaimer
I am fairly new to WPF, so my example may not be the optimum. I just thought it would help.

Giannis
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
breezbackAuthor Commented:
Hey Giannis,

Thanks for your comment, my program doesn't have any buttons that are triggered.
How can I do it with no user interaction at all.
0
Ioannis ParaskevopoulosCommented:
How is this handled then? Do you have a timer or something? Can you provide some sample code.
0
Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

breezbackAuthor Commented:
Let's say I have a command line that sends the counter "10"
The WPF should render 10 times, each time showing the counter.

For each render I need to do a snapshot with this code that is working:

private static void ExportAsImage(Fr<wbr ></wbr><wbr ></wbr>ameworkEle<wbr ></wbr>ment element, Counter counter)
        {

            element.DataContext = counter;
            var target = new RenderTargetBitmap((int)(7<wbr ></wbr><wbr ></wbr>20), (int)(620), 96, 96, PixelFormats.Pbgra32);
            target.Render(element);

            var encoder = new PngBitmapEncoder();
            var outputFrame = BitmapFrame.Create(target)<wbr ></wbr><wbr ></wbr>;
            encoder.Frames.Add(outputF<wbr ></wbr><wbr ></wbr>rame);

            var source = Guid.NewGuid().ToString("N<wbr ></wbr><wbr ></wbr>").Substri<wbr ></wbr>ng(0, 20) + ".png";
            using (var file = File.OpenWrite(source))
            {
                encoder.Save(file);
                //throw new Exception("done");
            }

        }

Open in new window


As you can see, my DataContext is called Counter - and I need to catch each Render event to produce 10 snapshots. I don't mind to use a Timer but this counter can also be very big (500)
0
breezbackAuthor Commented:
With a timer it solved my issue. Thanks for the help :)
0
breezbackAuthor Commented:
Need the Timer to make it work
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.