This question already has answers here:
Passing parameters between viewmodels
(2 answers)
Closed 8 years ago.
Goal:
When you click one of the rows in the lstView_bbb (in Test.xaml), the return value shall be return to the class MainWindow (MainWindow.xaml). And then, the Test.xaml shall be closed.
Problem:
I tried finding a solution that data of "_a" from row shall be transferred to the MainWIndow but it didn't go so well due to performance issue. I want to make it more efficient.
Information:
*I'm using WPF with VS 2013
*The return value is "_a" to the class MainWIndow.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="350" Width="525">
<Grid>
<Button x:Name="btn_test" Content="Test" HorizontalAlignment="Left" Margin="348,240,0,0" VerticalAlignment="Top" Width="75" Click="btn_test_Click"/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private List<aaa> _myList_aaa;
private void btn_test_Click(object sender, RoutedEventArgs e)
{
_myList_aaa = new List<aaa>();
for (int a = 1; a <= 5; a++)
{
aaa myaaa = new aaa();
myaaa._a = a;
myaaa._city = "New Yor";
myaaa._name = "jj jj jj";
_myList_aaa.Add(myaaa);
}
Test myTest = new Test(_myList_aaa);
myTest.ShowDialog();
}
}
public class aaa
{
public int _a { get; set; }
public string _name { get; set; }
public string _city { get; set; }
}
}
---------------------------------------
<Window x:Class="WpfApplication1.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test" Height="300" Width="300">
<Grid Background="#FFE5E5E5">
<ListView x:Name="lstView_bbb" SelectionMode="Single" ItemsSource="{Binding}" HorizontalAlignment="Left" Height="111" Margin="35,67,0,0" VerticalAlignment="Top" Width="222">
<ListView.View>
<GridView>
<GridViewColumn Header="name" Width="auto" DisplayMemberBinding="{Binding Path=_name}" TextBlock.TextAlignment="Left" />
<GridViewColumn Header="city" Width="auto" DisplayMemberBinding="{Binding Path=_city}" TextBlock.TextAlignment="Center" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Test.xaml
/// </summary>
public partial class Test : Window
{
public Test(IList<aaa> pAAA)
{
InitializeComponent();
lstView_bbb.DataContext = pAAA;
}
}
}
The easiest way is to create a property in Test:
class Test
{
public aaa SelectedItem
{
get
{
return lstView_bbb.SelectedItems[0] as aaa;
}
}
The best way is to use a ViewModel. Assign it to Test and use the same ViewModel in you other form to get the selected value.
Read the related MSDN article.
Related
I have a class that has several properties, one of which is editable, another of which is calculated based on the editable value. I want to initialize the editable value with something and allow the user to change it however they wish. However, I also want to have a reset button that puts the original value back into the textbox. I have a third variable that stores the value of the original number. However, I am not sure how I am supposed to access the object when the reset button is clicked to put the value back into the textbox. I've put the relevant code below (if I shouldn't be posting everything please let me know, still new to stackoverflow how-to):
Main Window
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 HDR_BED_Calc_local.Testers;
using HDR_BED_Calc_local.Helpers;
namespace HDR_BED_Calc_local
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//var window = new MainWindow();
this.DataContext = new fraction_doses(800, 700, 900, 800, 900, 1, 3);
}
}
}
XAML
<Window x:Class="HDR_BED_Calc_local.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:HDR_BED_Calc_local"
xmlns:uctesters="clr-namespace:HDR_BED_Calc_local.Testers"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<uctesters:fx_tester x:Name="fxtester_UC"/>
</Grid>
</Window>
Custom user control
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 HDR_BED_Calc_local.Helpers;
namespace HDR_BED_Calc_local.Testers
{
/// <summary>
/// Interaction logic for fx_tester.xaml
/// </summary>
public partial class fx_tester : UserControl
{
public fx_tester()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// What do I put here??
}
}
}
XAML
<UserControl x:Class="HDR_BED_Calc_local.Testers.fx_tester"
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:HDR_BED_Calc_local.Testers"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Background="White">
<StackPanel HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock xml:space="preserve">Fraction: </TextBlock>
<TextBlock Text="{Binding Path=fraction_number}"></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock xml:space="preserve">Current Dose: </TextBlock>
<TextBox x:Name="curr_fx_tb" Text="{Binding Path=editable_fraction_dose, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock xml:space="preserve">EQD2: </TextBlock>
<TextBlock Text="{Binding Path=this_fx_brachy_EQD2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
<Button Content="Reset" Click="Button_Click"/>
</StackPanel>
</UserControl>
Helper function with class
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace HDR_BED_Calc_local.Helpers
{
internal class fraction_doses : INotifyPropertyChanged
{
public int fraction_number { get; set; }
public double alpha_beta { get; }
private double _editable_fraction_dose;
public double editable_fraction_dose
{
get { return _editable_fraction_dose; }
set
{
_editable_fraction_dose = value;
calc_EQD2();
this.OnPropertyChanged("editable_fraction_dose");
}
}
public double actual_fraction_dose { get; }
public double pear_plan_dose { get; }
public double IMRT_plan_dose { get; }
public double max_dose_limit { get; }
public double preferred_dose_limit { get; }
private double _this_fx_brachy_EQD2;
public double this_fx_brachy_EQD2
{
get { return this._this_fx_brachy_EQD2; }
set
{
this._this_fx_brachy_EQD2 = value;
this.OnPropertyChanged("this_fx_brachy_EQD2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public fraction_doses(double current_dose, double pear_dose, double IMRT_dose, double max_dose_limit, double preferred_dose_limit, int fraction_number, int alpha_beta)
{
this.alpha_beta = alpha_beta;
this.actual_fraction_dose = current_dose;
this.editable_fraction_dose = current_dose;
this.pear_plan_dose = pear_dose;
this.IMRT_plan_dose = IMRT_dose;
this.max_dose_limit = max_dose_limit;
this.preferred_dose_limit = preferred_dose_limit;
this.fraction_number = fraction_number;
}
public void calc_EQD2()
{
// EQD2 is always reported in Gray even though we will be reporting cGy
double dose_Gy = this.editable_fraction_dose/100;
this.this_fx_brachy_EQD2 = Math.Round(1 * dose_Gy * (1+ dose_Gy / alpha_beta)/(1+2/alpha_beta), 2);
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You can try the following:
private void Button_Click(object sender, RoutedEventArgs e)
{
// What do I put here??
var dc = (fraction_doses ) this.DataContext:
if(dc!=null)
dc.Clear();
}
in your fraction_doses class add the method that clears the properties
public void Clear(){
this.MyProperty = MY_DEFAULT_VALUE;
//clear other properties..
}
I've used CaliburnMicro to implement data binding for my data grid:
<Window x:Class="TicketDemo.Views.ShellView"
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:TicketDemo.Views"
mc:Ignorable="d" FontSize="20"
Title="ShellView" Height="450" Width="800"
Closing="{Binding Path=OnClose}">
<Grid>
<DataGrid x:Name="Tickets" AlternatingRowBackground="LightGray" CanUserAddRows="True"
AutoGenerateColumns="False"
>
<DataGrid.Columns>
<DataGridTextColumn Header="Title" Binding="{Binding Path=Title}"/>
<DataGridTextColumn Header="Content" Binding="{Binding Path=Content}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
I tried to use the same data binding to link a method called OnClose() to the Closing event.
using Caliburn.Micro;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using TicketDemo.Models;
namespace TicketDemo.ViewModels
{
class ShellViewModel : Screen
{
public BindableCollection<TicketModel> Tickets { get; set; }
public ShellViewModel()
{
Tickets = SQLiteDataAccess.LoadTickets();
}
public void OnClose(object sender, EventArgs e)
{
MessageBox.Show("Window Closing");
}
}
}
When I debug the program, I get this message:
using Caliburn.Micro;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Shapes;
namespace TicketDemo.Views
{
/// <summary>
/// Interaction logic for ShellView.xaml
/// </summary>
public partial class ShellView : Window
{
public ShellView()
{
InitializeComponent();
MessageBox.Show("Hello");
}
}
}
System.Windows.Markup.XamlParseException: ''Provide value on
'System.Windows.Data.Binding' threw an exception.' Line number '9' and
line position '9'.'
InvalidCastException: Unable to cast object of type
'System.Reflection.RuntimeEventInfo' to type
'System.Reflection.MethodInfo'.
The SO post answering a question about this exception relates to buttons, but this is an event, so I don't think it's helpful to resolve my problem.
if you are using caliburn, the event is declared like this:
replace Closing="{Binding Path=OnClose}"
by
cal:Message.Attach="[Event Closing] = [Action OnClose]"
(dont forget to add xmlns:cal="http://www.caliburnproject.org")
in ViewModel you write:
public void OnClose()
{
MessageBox.Show("Window Closing");
}
I have made a list that is a property amnd then given that list values and this is still not working to place in a listview as a itemsource i have no idea how to fix this and get results is there anyone that can show me what im doing wrong here? i am placing the data context in the MainWindow
XAML
<Window x:Class="CRM.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:CRM"
mc:Ignorable="d"
Title="MainWindow" Height="1080" Width="1920">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="0*"/>
</Grid.ColumnDefinitions>
<ListView ItemsSource="{Binding tickets}" Margin="0,10,1075,0" MaxWidth="990"/>
</Grid>
</Window>
MainViewModel:
using API.Objects;
using API.ViewModels;
using System;
using System.Collections.Generic;
using System.Text;
namespace API.ViewModels
{
public class MainViewModel : BaseViewModel
{
int Counter{ get; set; }
List<TicketO> tickets { get; set;}
public MainViewModel()
{
TicketO ticket = new TicketO("Jens", "Svensson", "jenson1234#live.se", "0767942768", "This is working but my box is not", 500);
tickets.Add(ticket);
}
}
}
MainWindow
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 API.ViewModels;
namespace CRM
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
}
}
Make tickets public, DataContext = this; is missing, refer below link.
How can I bind a List as ItemSource to ListView in XAML?
i'm trying to learn WPF and on top of that the MVVM style of doing things.
I have a simple practice app in which i would like to display codes in a combo box.
My Code
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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;
namespace SteamCodes
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ObservableCollection<Codes> codes;
public MainWindow()
{
InitializeComponent();
codes = new ObservableCollection<Codes>()
{
new Codes() {CodeID = "1", Code="CODETEXT"}
};
steamCode.ItemsSource = codes.ToString();
}
}
public class Codes
{
public string CodeID { get; set; }
public string Code { get; set; }
}
}
My XAML
<Window x:Class="SteamCodes.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:SteamCodes"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ComboBox x:Name="steamCode" ItemsSource="{Binding Source = Codes}" HorizontalAlignment="Left" Height="43" Margin="122,37,0,0" VerticalAlignment="Top" Width="259"/>
</Grid>
</Window>
At the moment my Combo box is Pulling through as each option in the ComboBox is a letter from the line 'System.Collections.Objectmodel.ObservableCollection`1[SteamCodes.Codes]'
Everyone of those letters is a different drop down option in the combo box.
Any Ideas where i have gone wrong.
Your ComboBox ItemSource must be a collection of items, not a string:
steamCode.ItemsSource = codes;
You also have to specify which property of your item must be considered as value to be shown in combobox by setting DisplayMemberPath property:
steamCode.DisplayMemberPath = "Code";
To specify which property of bound objects will be used as actual selected value you have to use SelectedValuePath property:
steamCode.SelectedValuePath = "CodeID";
The MVVM approach is this:
public class ViewModel
{
public ObservableCollection<Codes> Codes { get; }
= new ObservableCollection<Codes>();
}
The MainWindow constructor:
public MainWindow()
{
InitializeComponent();
var viewModel = new ViewModel();
viewModel.Codes.Add(new Codes { CodeID = "1", Code = "CODETEXT" });
DataContext = viewModel;
}
The XAML:
<ComboBox ItemsSource="{Binding Codes}" DisplayMemberPath="Code" .../>
I have a simple wpf app, that I want to try to use ItemsSource binding from xaml. When I click the button. it should be updated also in the UI, but it doesn't.
Why doesn't it work?
Xaml code:
<Window x:Class="SendRawEthernetPacketsGUI.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<ComboBox HorizontalAlignment="Left" Margin="76,65,0,0" VerticalAlignment="Top" Width="120" ItemsSource="{Binding test}"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="90,171,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
C# code:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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.Shapes;
namespace SendRawEthernetPacketsGUI
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public ObservableCollection<string> test = new ObservableCollection<string>();
public Window1()
{
InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
test.Add("fdfddf");
}
}
}
It feels kinda stupid to even ask this, but even looking in google didn't help me. So can you?
Your binding never worked in the first place. You can only bind to properties not fields.
Try this instead:
public ObservableCollection<string> test { get; set; }
public Window1()
{
Test = new ObservableCollection<string>();
}
Or if you want some tricky C# 6 magic:
public ObservableCollection<string> test => new ObservableCollection<string>();
This is a function bodied-member and compiles to a read-only property that is initialized to the new ObservableCollection
Caveats/Design Errors:
Note that in both cases you aren't using INotifyPropertyChanged, so wholesale assignments to the collection won't be picked up by the UI. You should also be using PascalCase for your public properties, and using a proper view model instead of binding to the code-behind.