I'm newer to C# for UI WPF and I would like to set the value of Combobox?
cbx1.SelectedItem = "test 1";
This line show me every time null ( not an exception ) but the selectedItem is empty.
<telerik:RadComboBox Background="White" Foreground="{DynamicResource TitleBrush}" x:Name="cbx1" AllowMultipleSelection="True" VerticalAlignment="Center" HorizontalAlignment="Right" Width="200" Grid.Row="1" Grid.Column="0" Margin="0,14,11,14" Height="22"/>
Update :
I think that my question is not clear , I will give an example :
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.Collections.ObjectModel;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
ObservableCollection<Person> myPersonList = new ObservableCollection<Person>();
Person personJobs = new Person("Steve", "Jobs");
Person personGates = new Person("Bill", "Gates");
myPersonList.Add(personJobs);
myPersonList.Add(personGates);
MyComboBox.ItemsSource = myPersonList;
MyComboBox.SelectedItem = personGates;
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
}
}
In this code , if myCombobox.displayMemberPath = FirstName , How can I set the selected FirstName???
I do not have Teleriks Combobox, so I am using the standard Combobox here.
You should also know that XAML is very quiet, it do not throw an exception, but you will probably find an error message in the Output window.
This example is following the MVVM pattern. This means that you will find most of the code in the PersonViewModel class (the "View Model") where the properties are bound to the View. (I am not using the Model here, but that could be a data source class).
The PersonViewModel is inheriting the VMBase where the that notifies the View about changes in properties.
So, to your problem: I have added a property "SelectedPerson". This property is bound to the SelectedItem in the control. So each time you change the item in the combobox the SelectedPerson will contain the selected Person object.
I have also added a button "Select Steve" that will, In the PersonViewModel, find the Person object with firstname = "Steve" and set the SelectedPerson to that object. The Combobox will change to "Steve".
Window1.xaml
<Window x:Class="SO65149368.Window1"
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:SO65149368"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<StackPanel>
<ComboBox Name="MyComboBox" Width="300" HorizontalAlignment="Left" Margin="5"
ItemsSource="{Binding myPersonList}"
DisplayMemberPath="FirstName"
SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"/>
<StackPanel Orientation="Horizontal">
<Button x:Name="SelectSteve" Content="Select Steve" Click="SelectSteve_Click"
Margin="5"/>
</StackPanel>
</StackPanel>
</Window>
Window1.xaml.cs
using System.Windows;
namespace SO65149368
{
public partial class Window1 : Window
{
public PersonViewModel PersonViewModel = new PersonViewModel();
public Window1()
{
DataContext = PersonViewModel;
InitializeComponent();
}
private void SelectSteve_Click(object sender, RoutedEventArgs e)
{
PersonViewModel.SelectSteve();
}
}
}
PersonViewModel.cs
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
namespace SO65149368
{
public class PersonViewModel : VMBase
{
public ObservableCollection<Person> myPersonList { get; } = new ObservableCollection<Person>();
public PersonViewModel()
{
Person personJobs = new Person("Steve", "Jobs");
Person personGates = new Person("Bill", "Gates");
myPersonList.Add(personJobs);
myPersonList.Add(personGates);
SelectedPerson = personGates;
//MyComboBox.ItemsSource = myPersonList;
//MyComboBox.SelectedItem = personGates;
}
public Person SelectedPerson
{
get { return _selectedPerson; }
set
{
Set(ref _selectedPerson, value);
Debug.WriteLine("Selected person: " + SelectedPerson.FirstName + " " + SelectedPerson.LastName);
}
}
private Person _selectedPerson;
public void SelectSteve()
{
SelectedPerson = myPersonList.FirstOrDefault(p => p.FirstName == "Steve");
}
}
}
VMBase.cs
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace SO65149368
{
public abstract class VMBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool Set<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
return false;
}
}
}
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 have a WPF window that contains multiple user controls, some of which are invisible (Visibility = Hidden). One of these controls has a ComboBox that has an ItemsSource binding, and I want to preset its selected item while the window/control is loading.
However, it seems like the binding is not applied until the combobox is visible. When I go to set the SelectedItem property and I hit a breakpoint in the debugger, I notice that ItemsSource is null at that moment. Is there a way to force WPF to apply the data binding and populate the combobox while it stays invisible?
Reproducible Example:
MainWindow.xaml
<Window x:Class="HiddenComboBoxBinding.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:HiddenComboBoxBinding"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Border x:Name="comboboxParent" Visibility="Collapsed">
<ComboBox x:Name="cmbSearchType" SelectedIndex="0" ItemsSource="{Binding SearchTypeOptions}" DisplayMemberPath="Name" SelectionChanged="cmbSearchType_SelectionChanged" />
</Border>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace HiddenComboBoxBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ViewModel viewModel { get; set; } = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = viewModel;
// Add some or all of our search types - in the real code, there's some business logic here
foreach (var searchType in SearchType.AllSearchTypes)
{
viewModel.SearchTypeOptions.Add(searchType);
}
// Pre-select the last option, which should be "Bar"
cmbSearchType.SelectedItem = SearchType.AllSearchTypes.Last();
}
private void cmbSearchType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
}
ViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HiddenComboBoxBinding
{
public class ViewModel : INotifyPropertyChanged
{
public ObservableCollection<SearchType> SearchTypeOptions { get; set; } = new ObservableCollection<SearchType>();
#region INotifyPropertyChanged Members
private void NotifyPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
public class SearchType
{
// Source list of Search Types
private static List<SearchType> _AllSearchTypes;
public static List<SearchType> AllSearchTypes
{
get
{
if(_AllSearchTypes == null)
{
_AllSearchTypes = new List<SearchType>();
_AllSearchTypes.Add(new SearchType() { Name = "Foo" });
_AllSearchTypes.Add(new SearchType() { Name = "Bar" });
}
return _AllSearchTypes;
}
}
// Instance properties - for the purposes of a minimal, complete, verifiable example, just one property
public string Name { get; set; }
}
}
I was able to figure out the issue. Setting the SelectedItem actually did work (even though ItemsSource was null at that time) but in the XAML, the ComboBox had SelectedIndex="0" and it was taking precedence over the SelectedItem being set in the code-behind.
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 button with a context menu associated to it. I can right click on the button and show the context menu as you would expect, however I want to be able to show the context menu after another event, such as a left click, or a drag and drop style event.
I am attempting to do this by binding the IsOpen property of the context menu to the view model, but this is not working as expected. On first left click of the button, nothing happens, although I can see the property on the view model that IsOpen is bound to being updated correctly.
If I right click, the menu will display correctly, and after this if I left click the menu will also show.
Has anyone ever seen this or have any ideas on what I need to do to get the contextMenu to open when the IsOpen property is updated?
XAML
<Window x:Class="PopUpTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mvp="clr-namespace:PopUpTest"
Title="MainWindow" Height="350" Width="525" x:Name="This">
<Window.DataContext>
<mvp:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.Resources>
<ContextMenu x:Key="Menu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" IsOpen="{Binding PopupViewModel.IsOpen, Mode=TwoWay}">
<MenuItem Header="Delete" />
</ContextMenu>
</Grid.Resources>
<Button Command="{Binding DisplayPopupCommand}" ContextMenu="{StaticResource Menu}" Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type Grid}}}"/>
</Grid>
Code Behind
using System;
using System.Collections.Generic;
using System.ComponentModel;
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 Microsoft.Practices.Prism.Commands;
namespace PopUpTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class MainWindowViewModel : BaseViewModel
{
private readonly PopupViewModel<ChildViewModel> _popupViewModel;
private readonly DelegateCommand _displayPopupCommand;
public MainWindowViewModel()
{
_popupViewModel = new PopupViewModel<ChildViewModel>(new ChildViewModel { FirstName = "John", LastName = "Doe" });
_displayPopupCommand = new DelegateCommand(() => { PopupViewModel.IsOpen = PopupViewModel.IsOpen == false; Console.WriteLine(PopupViewModel.IsOpen); });
}
public ICommand DisplayPopupCommand
{
get { return _displayPopupCommand; }
}
public PopupViewModel<ChildViewModel> PopupViewModel
{
get { return _popupViewModel; }
}
}
public class PopupViewModel<T> : BaseViewModel
{
private readonly T _data;
public PopupViewModel(T data)
{
_data = data;
}
public T Data
{
get { return _data; }
}
private bool _isOpen;
public bool IsOpen
{
get { return _isOpen; }
set
{
if (_isOpen != value)
{
_isOpen = value;
OnPropertyChanged("IsOpen");
}
}
}
}
public class ChildViewModel : BaseViewModel
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
if (_firstName != value)
{
_firstName = value;
OnPropertyChanged("FirstName");
}
}
}
private string _lastName;
public string LastName
{
get { return _lastName; }
set
{
if (_lastName != value)
{
_lastName = value;
OnPropertyChanged("LastName");
}
}
}
}
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I have been able to solve this by introducing a BindingProxy to the XAML as described in the answer to this post on the MSDN forums:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/a4149979-6fcf-4240-a172-66122225d7bc/wpf-mvvm-contextmenu-binding-isopen-to-view-model?forum=wpf
The binding proxy gets around the issue where the ContextMenu does not have a DataContext until it first displays after a right click.
The issue is discussed further here:
http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/
I'm making a Contact info program, where users can enter there name, age and birthday and some other things into textboxes. When you click ok, I want the data to be put into the DataGrid.
First I have my MainWindow, which opens a new window called CreateContact when you press the Create new contact button:
CreateContact cc = new CreateContact();
cc.ShowDialog();
then a new window open, where you type your name and age and choose the birthdate. Then you click OK:
private void cmdOk_Click(object sender, RoutedEventArgs e)
{
MainWindow m = new MainWindow();
m.name = txtName.Text;
m.age = txtAge.Text;
m.birthDate = dpBirthdate.Text;
m.ShowContacts()
}
which should run my method ShowContacts in my MainWindow:
public string name;
public string age;
public string birthDate;
public void ShowContacts()
{
try
{
dgContacts.ItemsSource = LoadContactData();
}
catch (Exception e)
{
MessageBox.Show("" + e);
}
}
private List<ContactData> LoadContactData()
{
List<ContactData> list = new List<ContactData>();
list.Add(new ContactData()
{
Name = name,
Age = age,
BirthDate = birthDate
});
return list;
}
public class ContactData
{
public string Name { get; set; }
public string Age { get; set; }
public string BirthDate { get; set; }
}
But nothing happens, I get no data in the DataGrid. I hope someone can tell me what is wrong. I have really tried searching a lot on what is causing the DataGrid to show no data.
Assuming the dgContacts is the datagrid view control, you have to call the following command to ensure that the data is bound
dgContacts.DataBind();
The procedure is similar to the one that is explained here.
In case you have debugged the code, and this suggestion is not working, please debug and post whether the data that is bound to the control.
Short answer: looks like you're not firing the PropertyChanged event when you change the ItemsSource in ShowContacts.
Long answer: you should really look into MVVM. You should just create a ViewModel that maintains a list of ContactData, and bind to that list in your XAML (also databind your Contact dialog to a ContactData object):
var contact = new ContactData();
var cc = new CreateContact { Datacontext = contact };
cc.ShowDialog();
// ok button has been hit at this point,
// you can check for cancel if you want
(List<ContactData>)(dgContacts.ItemsSource).Add(contact);
// may still need to fire PropertyChanged here depending on binding
Okay, here is all the xaml and classes i use in the program. I really hope someone can help tell, what is wrong and why it wont show any data in the datagrid.
MainWindow.xaml:
<Window x:Class="KontaktInfo.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>
<DataGrid AutoGenerateColumns="True" Name="dgContacts" HorizontalAlignment="Left" Margin="0,95,0,0" VerticalAlignment="Top" Height="225" Width="517"/>
<Button x:Name="cmdCreateContact" Content="Opret Kontakt" HorizontalAlignment="Left" Margin="0,68,0,0" VerticalAlignment="Top" Width="80" Click="cmdCreateContact_Click"/>
<Button x:Name="cmdDeleteContact" Content="Slet Kontakt" HorizontalAlignment="Left" Margin="85,68,0,0" VerticalAlignment="Top" Width="80"/>
</Grid>
MainWindow.cs:
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 KontaktInfo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public string name;
public string age;
public string birthDate;
public MainWindow()
{
InitializeComponent();
}
private void cmdCreateContact_Click(object sender, RoutedEventArgs e)
{
CreateContact cc = new CreateContact();
cc.ShowDialog();
}
public void ShowContacts()
{
try
{
dgContacts.ItemsSource = LoadContactData();
}
catch (Exception e)
{
MessageBox.Show("" + e);
}
}
private List<ContactData> LoadContactData()
{
List<ContactData> list = new List<ContactData>();
list.Add(new ContactData()
{
Name = name,
Age = age,
BirthDate = birthDate
});
return list;
}
}
public class ContactData
{
public string Name { get; set; }
public string Age { get; set; }
public string BirthDate { get; set; }
}
}
CreateContact.xaml:
<Window x:Class="KontaktInfo.CreateContact"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CreateContact" Height="403" Width="300">
<Grid>
<Label Content="Navn" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txtName" HorizontalAlignment="Left" Height="23" Margin="10,36,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="272"/>
<Label Content="Alder" HorizontalAlignment="Left" Margin="10,64,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txtAge" HorizontalAlignment="Left" Height="23" Margin="10,90,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="272"/>
<Label Content="Fødselsdag" HorizontalAlignment="Left" Margin="10,118,0,0" VerticalAlignment="Top"/>
<Button Name="cmdOk" Content="OK" HorizontalAlignment="Left" Margin="127,341,0,0" VerticalAlignment="Top" Width="75" Click="cmdOk_Click"/>
<Button Name="cmdCancel" Content="Annuller" HorizontalAlignment="Left" Margin="207,341,0,0" VerticalAlignment="Top" Width="75"/>
<DatePicker Name="dpBirthdate" HorizontalAlignment="Left" Margin="10,144,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>
CreateContact.cs:
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 KontaktInfo
{
/// <summary>
/// Interaction logic for CreateContact.xaml
/// </summary>
public partial class CreateContact : Window
{
public CreateContact()
{
InitializeComponent();
}
private void cmdOk_Click(object sender, RoutedEventArgs e)
{
MainWindow m = new MainWindow();
m.name = txtName.Text;
m.age = txtAge.Text;
m.birthDate = dpBirthdate.Text;
m.ShowContacts();
}
}
}