I cannot get DataGrid binding to work in the example bellow.
Any clues on what's going on ?
namespace WPFTestApplication
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public class Person
{
public int age { get; set; }
public String Name { get; set; }
public Person(int age, String Name)
{
this.age = age;
this.Name = Name;
}
}
public class MegaObject
{
public IList<Person> persons { get; set; }
public MegaObject()
{
persons = new List<Person>();
persons.Add(new Person(11, "A"));
persons.Add(new Person(12, "B"));
persons.Add(new Person(13, "C"));
}
}
public Window1()
{
InitializeComponent();
MegaObject myobject= new MegaObject();
DataContext = myobject;
}
}
}
<Grid>
<my:DataGrid
Name="dataGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding Source=persons}"
>
<my:DataGrid.Columns>
<my:DataGridTextColumn Binding="{Binding Path=age, Mode=TwoWay}" >
</my:DataGridTextColumn>
<my:DataGridTextColumn Binding="{Binding Path=Name, Mode=TwoWay}" >
</my:DataGridTextColumn>
</my:DataGrid.Columns>
</my:DataGrid>
</Grid>
Regards,
MadSeb
The ItemsSource binding needs to have Path set, not Source, to persons. Simply putting it as {Binding persons} would do the trick (Path is the default property in markup) or explicitly {Binding Path=persons}. The DataContext is always inherited.
Related
I have a datagrid which is bound to my ObservableCollection.
Each column is bound to property of the class wellenelement.
Now i would like to convert the column "Art" to a combobox column, where the user can choose from 3 different options.
How can i create these 3 Combobox items and add it to the datagrid?
<DataGrid AutoGenerateColumns="True" Name="dataGrid1" ItemsSource="{Binding}" >
</DataGrid>
```xaml
```c#
public partial class MainWindow : Window
{
public ObservableCollection<Wellenelement> Welle1;
public MainWindow()
{
InitializeComponent();
Welle1 = new ObservableCollection<Wellenelement>();
dataGrid1.DataContext = Welle1;
}
}
```c#
```c#
public class Wellenelement
{
public string Art { get; set; }
public string UK { get; set; }
public string DA { get; set; }
public string DI { get; set; }
}
```c#
If it's the same for each item you can add a collection to the viewmodel and add it as a resource to your view. Then you can set the resource as the itemssource for the DataGridComboBoxColumn.
ViewModel:
public class MainViewModel
{
public MainViewModel()
{
Wellenelements = new ObservableCollection<Wellenelement>()
{
new Wellenelement()
{
UK = "uk1",
DA = "da1",
DI = "di1"
},
new Wellenelement()
{
UK = "uk2",
DA = "da2",
DI = "di2"
},
};
ArtTypes = new List<string>()
{
"new art","old art", "good art","bad art"
};
}
public ObservableCollection<Wellenelement> Wellenelements { get; set; }
public List<string> ArtTypes { get; set; }
}
View:
<Window ...
xmlns:viewmodels="clr-namespace:WpfApp.Viewmodels"
...>
<Window.DataContext>
<viewmodels:MainViewModel/>
</Window.DataContext>
<Window.Resources>
<CollectionViewSource x:Key="myCollection" Source="{Binding ArtTypes}"/>
</Window.Resources>
<Grid>
<DataGrid AutoGenerateColumns="False"
CanUserAddRows="False"
ItemsSource="{Binding Wellenelements}" >
<DataGrid.Columns>
<DataGridComboBoxColumn ItemsSource="{Binding Source={StaticResource myCollection}}"
SelectedItemBinding="{Binding Art, UpdateSourceTrigger=PropertyChanged}"
Header="Art Combo column"/>
<DataGridTextColumn Binding="{Binding Art}"
IsReadOnly="True"
Header="Selected Art Type"/>
<DataGridTextColumn Binding="{Binding UK}"
Header="UK"/>
<DataGridTextColumn Binding="{Binding DA}"
Header="DA"/>
<DataGridTextColumn Binding="{Binding DI}"
Header="DI"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Wellenelement class:
public class Wellenelement : ObservableObject
{
public string UK { get; set; }
public string DA { get; set; }
public string DI { get; set; }
private string _art;
public string Art
{
get { return _art; }
set
{
_art = value;
OnPropertyChanged(nameof(Art));
}
}
}
Consider the following XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:WpfApplication1"
DataContext="{Binding Source={x:Static c:ViewModel.Instance}}"
>
<Grid>
<DataGrid DataContext="{Binding ItemsViewSource}" ItemsSource="{Binding}" />
</Grid>
and the view model:
public class ItemViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class ViewModel
{
public static ViewModel Instance { get; set; }
static ViewModel()
{
Instance = new ViewModel();
}
public ObservableCollection<ItemViewModel> Items { get; private set; }
public CollectionViewSource ItemsViewSource { get; private set; }
public ViewModel()
{
Items = new ObservableCollection<ItemViewModel>();
ItemsViewSource = new CollectionViewSource() { Source = Items };
Items.Add(new ItemViewModel() { FirstName = "test", LastName = "test" });
}
}
This code is working, but if I change
<DataGrid DataContext="{Binding ItemsViewSource}" ItemsSource="{Binding}" />
to
<DataGrid ItemsSource="{Binding ItemsViewSource}" />`
DataGrid does not bind, it is empty.
What is the difference between these two bindings?
First of all for second option to work, you need to bind with CollectionViewSource.View property.
<DataGrid ItemsSource="{Binding ItemsViewSource.View}" />
When you bind DataContext of dataGrid to CollectionViewSource, dataGrid internally do value conversion from CollectionViewSource to ICollectionView (ListCollectionView in your case) but when you asked it explicitly to bind to CollectionViewSource, it doesn't do default value conversion. You can verify this by putting converter in your binding.
Is it possible to bind a datagrid to only selective members of a class?
The way I have made the binding presently, all the class variables have been binded(one to one mapped) to datagrid's columns.
private void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
Now i want only a few class properties(not all) to be binded to the datagrid.
Yes, Just turn off the AutoGenerateColumns and manually specify them
In MainWindow.xaml
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Hello}" Header="Hello" />
<DataGridTextColumn Binding="{Binding World}" Header="World" />
</DataGrid.Columns>
</DataGrid>
In MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new[] { new FakeViewModel() };
}
}
In FakeViewModel.cs
namespace WpfApplication4
{
class FakeViewModel
{
public FakeViewModel()
{
Hello = "Hello";
World = "World";
Then = DateTime.Now;
}
public DateTime Then { get; set; }
public string Hello { get; set; }
public string World { get; set; }
}
}
Please note the unused Property Then!
XAML
<df:DataForm x:Name="MobCrud"
AutoEdit="True"
AutoCommit="True"
AutoGenerateFields="False"
VerticalAlignment="Top"
CommandButtonsVisibility="All"
Header="Mob Details"
CanUserAddItems="True"
CanUserDeleteItems="True"
CurrentItem="{StaticResource newMob}"
>
<df:DataForm.Fields>
<df:DataFormTextField Binding="{Binding Name}" FieldLabelContent="Name" />
<df:DataFormTextField Binding="{Binding Title}" FieldLabelContent="Title"/>
<df:DataFormComboBoxField x:Name="AuraList" Binding="{Binding Aura}" FieldLabelContent="Aura"/>
</df:DataForm.Fields>
Code:
public enum Auras
{
Holy,
Fire,
Frost,
}
public class MobDetail : IEditableObject
{
public string Name { get; set; }
public string Title { get; set; }
public Auras Aura { get; set; }
public override string ToString() { return Name; }
public void BeginEdit(){}
public void EndEdit(){}
public void CancelEdit(){}
}
The DataForm ItemsSource is bound to an ObservableCollection()
What do I need to do to populate and initialize the dropdown?
Answer is to use a converter:
<df:DataFormComboBoxField
x:Name="AuraList"
Binding="{Binding Aura, Mode=TwoWay,
Converter={StaticResource enumSelectedValueConverter}}"
FieldLabelContent="Aura"/>
and set the ItemsSource on the form Loaded event
(MobCrud.Fields[2] as DataFormComboBoxField).ItemsSource =
Enums.GetStringArray(typeof(Auras));
See here for the full story:
Creating-Rich-Data-Forms-in-Silverlight-3-Customization
I have a class with an ObservableCollection called List and I am trying to bind to textboxes individually. I have been trying:
<TextBox Text="{Binding Source=List[0], Path=Value}" />
<TextBox Text="{Binding Source=List[1], Path=Value}"/>
The StringObject class is just:
class StringObject
{
public string Value { get; set; }
}
Can someone advise?
If this is for a WPF app.
Given this code behind:
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
this.DataContext = new ListCon();
}
}
public class ListCon
{
public List<StringObject> List
{
get
{
var list = new List<StringObject>();
list.Add(new StringObject() { Value = "Hello World" });
return list;
}
}
}
public class StringObject
{
public string Value { get; set; }
}
The binding would look like this:
<TextBox Text="{Binding List[0].Value}" />