0

I need help to understand Multiple ViewModel communication in Wpf.

(1): I have MainWindowViewModel which loads image and display in MainWindow.

(2): I have ChildWindowViewModel contain button to convert image to grayimage

I have to pass input image from mainviewmodel to childviewmodel to apply gray operation when event is fired in childwindow and after applying operation i have to return modified image to mainviewmodel to display in mainwindow

I have tried doing some codebehind thing by passing mainwindow to childviewmodel and it worked, Now i have to achieve this with pure mvvm architecture

Give me suggestion, thanks in advance :)

MainWindow:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="30"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Grid Grid.Row="0" >
        <StackPanel Orientation="Horizontal">
            <Button Content="Load Image" Command="{Binding OpenImg}"/>
            <Button Content="Child Window" Command="{Binding ChildWin}"/>
        </StackPanel>
    </Grid>
    <Grid Grid.Row="1" >
        <Viewbox Margin="5,5,5,5">
            <Image x:Name="image" Source="{Binding Image}"/>
        </Viewbox>
    </Grid>

</Grid>

MainWindowViewModel:

public class MainWindowViewModel : ViewModelBase
  {
    public ICommand OpenImg { get; set; }

    Bitmap bitmap;

    public MainWindowViewModel()
    {
        OpenImg = new RelayCommand(LoadImage);
    }

    private BitmapImage _image;
    public BitmapImage Image
    {
        get { return _image; }
        set
        {
            _image = value;
            RaisePropertyChanged("Image");
        }
    }

    private void LoadImage()
    {
        OpenFileDialog op = new OpenFileDialog();
        op.Title = "Select a Picture";
        op.Filter = "Images (*.BMP;*.JPG;*.GIF;*.PNG;*.TIFF)|*.BMP;*.JPG;*.GIF;*.PNG;*.TIFF|" +
            "All files (*.*)|*.*";
        op.Multiselect = true;
        if (op.ShowDialog() == true)
        {
            Image = new BitmapImage(new Uri(op.FileName));
            bitmap = new Bitmap(op.FileName);
        }
    }

    private RelayCommand _childWin;
    public ICommand ChildWin
    {
        get
        {`enter code here`
            if (_childWin == null)
            {
                _childWin = new RelayCommand(DisplayChildWin);
            }
            return _childWin;
        }
    }

    private void DisplayChildWin()
    {
        ChildWindow childWindow = new ChildWindow();
        childWindow.ShowDialog();
    }
}

ChildWindow:

<Grid>

    <Button Content="Convert To GrayImage" Command="{Binding ApplyGray}" Width="150" Height="30" />

</Grid>

ChildWindowViewModel:

 public class ChildWindowViewModel : ViewModelBase
  {
    public ChildWindowViewModel()
    {
    }

    private RelayCommand _applyGray;
    public ICommand ApplyGray
    {
        get
        {
            if (_applyGray == null)
            {
                _applyGray = new RelayCommand(ApplyGrayScale);
            }
            return _applyGray;
        }
    }

    private void ApplyGrayScale()
    {

    }
}

GrayConversion Class:

   public static class GrayScale
    {
    public static Bitmap ApplyGray(Bitmap bmp)
    {
        //get image dimension
        int width = bmp.Width;
        int height = bmp.Height;

        //color of pixel
        Color p;

        //grayscale
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                //get pixel value
                p = bmp.GetPixel(x, y);

                //extract pixel component ARGB
                int a = p.A;
                int r = p.R;
                int g = p.G;
                int b = p.B;

                //find average
                int avg = (r + g + b) / 3;

                //set new pixel value
                bmp.SetPixel(x, y, Color.FromArgb(a, avg, avg, avg));
            }
        }
        return bmp;
    }
}
Karthik N
  • 61
  • 2
  • 12

1 Answers1

0

You could think about makeing your ViewModel Singelton

    private static ViewModel _createInstance = null;

    public static ViewModel CreateInstance
    {

        get
        {
            if (null == _createInstance)
            {
                _createInstance = new ViewModel();
            }

            return _createInstance;
        }
    }//END CreateInstance

and access it using the createInstance function like so:

    ViewModel.CreateInstance.TheImageYouWantToAccess
Denis Schaf
  • 2,478
  • 1
  • 8
  • 17
  • **Create**Instance is an awkward name for a singleton accessor property. Nothing is created if you call it a second time. Besides that, many people consider singleton an anti-pattern: https://stackoverflow.com/questions/12755539/why-is-singleton-considered-an-anti-pattern – Clemens Jan 17 '19 at 15:01
  • I agree about hte name getInstance makes a whole lot more sense! Regarding it beeing an antipattern...mhhhm...yes true that but why is it considered an antipattern? As far as I am aware it is considered an antipattern because it creates dependencies between multible classes (correct me if i am wrong on this one). But that is exactly what was requested above...right? – Denis Schaf Jan 17 '19 at 15:07
  • accessing it using createinstance throws a null reference exception. – Karthik N Jan 18 '19 at 05:28