I have a User control with a button. when click on the button create a random number. I want use this number in Main Window. I use user control for 3 time in my Main Window. but I can't get the number in main window. I use MVVM. Please help me!
UserControl.xaml
<UserControl x:Class="test.UserControl1"
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"
xmlns:local="clr-namespace:test"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="300">
<Grid>
<Grid.DataContext>
<local:UserControl1VM/>
</Grid.DataContext>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=txt}"/>
<Button Grid.Column="1" Content="Show Num" Command="{Binding Path=AddNum}"/>
</Grid>
</UserControl>
User Contorl View Model
public class UserControl1VM : INotifyPropertyChanged
{
private string _txt;
public string txt
{
get { return _txt; }
set
{
_txt = value;
OnPropertyChanged("txt");
}
}
public RelayCommand AddNum { get; set; }
public UserControl1VM()
{
AddNum = new RelayCommand(DoAddNum);
}
private void DoAddNum(object obj)
{
Random random = new Random();
txt = random.Next(0, 100).ToString();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainWindow.xaml
<Window x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:test"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<UniformGrid Rows="4">
<local:UserControl1 Margin="20"/>
<local:UserControl1 Margin="20"/>
<local:UserControl1 Margin="20"/>
<UniformGrid Columns="2" Margin="20">
<TextBlock Text="{Binding Path=Sum}"/>
<Button Content="Sum" Command="{Binding Path=AddSum}"/>
</UniformGrid>
</UniformGrid>
Main Window View Model
public class MainWindowVM : INotifyPropertyChanged
{
private string _Sum;
public string Sum
{
get { return _Sum; }
set
{
_Sum = value;
OnPropertyChanged("Sum");
}
}
public RelayCommand AddSum { get; set; }
public MainWindowVM()
{
AddSum = new RelayCommand(DoAddSum);
}
private void DoAddSum(object obj)
{
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
RelayCommand.cs
public class RelayCommand : ICommand
{
private string v;
private Action<object> MyAction { get; set; }
public RelayCommand(Action<object> MyAction)
{
this.MyAction = MyAction;
}
public RelayCommand(string v)
{
this.v = v;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
MyAction(parameter);
}
}
I want When click on "Sum" show Sum of 3 numbers in the text block.
My suggestions
change 'sum' and 'txt' property types to int - sum up is easier on numbers ;-)
use a composite pattern on your ViewModels. Let the MainWindow view model consist of three UserControlVM's.
Changes
1.) Changes to MainWindow.xaml
<UniformGrid Rows="4">
<UniformGrid.DataContext>
<local:MainWindowVM/>
</UniformGrid.DataContext>
<local:UserControl1 Margin="20" DataContext="{Binding UserControlVM1}"/>
<local:UserControl1 Margin="20" DataContext="{Binding UserControlVM2}"/>
<local:UserControl1 Margin="20" DataContext="{Binding UserControlVM3}"/>
2.) Remove from UserControl1.xaml:
<Grid.DataContext>
<local:UserControl1VM/>
</Grid.DataContext>
3.) Change MainWindowVM.cs
public class MainWindowVM : INotifyPropertyChanged
{
private readonly List<UserControl1VM> childVms;
public UserControl1VM UserControlVM1 { get; set; }
public UserControl1VM UserControlVM2 { get; set; }
public UserControl1VM UserControlVM3 { get; set; }
public MainWindowVM()
{
childVms = new List<UserControl1VM>()
{
new UserControl1VM(),
new UserControl1VM(),
new UserControl1VM(),
};
UserControlVM1 = childVms[0];
UserControlVM2 = childVms[1];
UserControlVM3 = childVms[2];
AddSum = new RelayCommand(DoAddSum);
}
private int _Sum;
public int Sum
{
get { return _Sum; }
set
{
_Sum = value;
OnPropertyChanged("Sum");
}
}
public RelayCommand AddSum { get; set; }
private void DoAddSum(object obj)
{
childVms.ForEach(vm => Sum += vm.txt);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}