Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update the value of a row of a WPF DataGrid from IronPython?

I have a simple WPF application. Here is the WPF code

<Window 
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       Title="WpfApplication3" Height="300" Width="300"> 
       <Grid>
        <DataGrid x:Name="dg" Margin="0" Height="149" Width="136">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding value}" ClipboardContentBinding="{x:Null}"/>
            </DataGrid.Columns>
        </DataGrid>
        <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="109,230,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
    </Grid>
</Window>

and here is the python code:

import wpf

from System.Windows import Application, Window, MessageBox
from time import sleep

class MyWindow(Window):
    def __init__(self):
        self.value = Value()
        wpf.LoadComponent(self, 'WpfApplication3.xaml')

        self.dg.Items.Add(self.value)

    def button_Click(self, sender, e):
        self.value.increment()
        MessageBox.Show(str(self.value.value))

class Value:
    def __init__(self):
        self.value = 1

    def increment(self):
        self.value += 1

if __name__ == '__main__':
    Application().Run(MyWindow())

The behavior that I expect is that on clicking button, the value in the DataGrid should update. When I launch the application, an entry is places in the column with a value of 1, but it is not updating on the button click. The MessageBox confirms that the value is being updated, but the DataGrid is not seeing that the value is updated. Where am I going wrong?

like image 237
crf Avatar asked May 15 '15 19:05

crf


1 Answers

Ok, I'm not familiar with Python so correct me if I'm wrong but I think your code will look like something like this in C#:

public partial class MainWindow : Window
{
    public Value value;
    public MainWindow()
    {
        InitializeComponent();
        value = new Value();
        dg.Items.Add(value);
    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        value.Increament();
        MessageBox.Show(Convert.ToString(value.value));
    }
}

public class Value 
{
    public int value;
    public Value()
    {
        value = 1;
    }
    public void Increament()
    {
        value++;
    }
}

Now for Binding="{Binding value}" in the XAML to work, two changes have to be made:

(1) The DataContext must be set. This can be easily done as follow:

import wpf

from System.Windows import Application, Window, MessageBox
from time import sleep

class MyWindow(Window):
    def __init__(self):
        self.value = Value()
        wpf.LoadComponent(self, 'WpfApplication3.xamll')

        self.dg.DataContext = self
        self.dg.Items.Add(self.value)

    def button_Click(self, sender, e):
        self.value.increment()
        MessageBox.Show(str(self.value.value))

(2) The Value class must implement INotifyPropertyChanged. Therefore the following is the correct implementation of this class in C#:

public class Value : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    int _value;
    public int value
    {
        get
        {
            return _value;
        }
        set
        {
            _value = value; OnPropertyChanged("value");
        }
    }
    public Value()
    {
        value = 1;
    }
    public void Increament()
    {
        value++;
    }
}

From what I understand by reading this Blog (which since I don't know no python you should definitely read it) It is possible to implement INotifyPropertyChanged in IronPython. To achieve that, you should let your Valueclass implements INotifyPropertyChanged :

from System.ComponentModel import INotifyPropertyChanged
from System.ComponentModel import PropertyChangedEventArgs

class Value(INotifyPropertyChanged):
    def __init__(self):
        self.propertyChangedHandlers = []
        self.value= 1

    def RaisePropertyChanged(self, propertyName):
        args = PropertyChangedEventArgs(propertyName)
        for handler in self.propertyChangedHandlers:
            handler(self, args)

    def add_PropertyChanged(self, handler):
        self.propertyChangedHandlers.append(handler)

    def remove_PropertyChanged(self, handler):
        self.propertyChangedHandlers.remove(handler)


    def Increament(self):
        self.value += 1
        self.RaisePropertyChanged("value")
like image 135
Bahman_Aries Avatar answered Oct 04 '22 00:10

Bahman_Aries