I have a class Person with three properties Name, LastName and FullName.
I use MVVM - in the ModelView, I have a List<Person> Persons.
My view looks like this:
<Button Content="LastName" Command="{Binding LastNameCommand, Mode=OneWay}" />
<ListView IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Persons}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Name"
DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="FullName"
DisplayMemberBinding="{Binding FullName}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
My goal is now to change the part
<GridViewColumn Header="Name"
DisplayMemberBinding="{Binding Name}" />
to
<GridViewColumn Header="LastName"
DisplayMemberBinding="{Binding LastName}" />
when I click on the button.
How can I achieve that?
Setting or changing the DisplayMemberBinding property of a GridViewColumn should be done in the view.
The view model shouldn't know or care about any DisplayMemberBinding. It only updates the source properties (Name and FullName in this case).
So hook up an event handler for the button in the view and set the view-related property there:
private void Button_Click(object sender, RoutedEventArgs e)
{
col1.DisplayMemberBinding = new Binding("path");
}
XAML:
<Button Content="LastName" Click="Button_Click" Command="{Binding LastNameCommand, Mode=OneWay}" />
<ListView IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Persons}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn x:Name="col1" Header="Name" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn x:Name="col2" Header="FullName" DisplayMemberBinding="{Binding FullName}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
This does not break the MVVM pattern in any way. Trying to modify a DisplayMemberBinding in a view model certainy does. MVVM is not about eliminating view-related code from the views. It's about separation of concerns.
Related
So I've used the '*' key to divide the total width into different areas that are responsive. But obviously I can't use grid everywhere, some elements don't support it etc. So my question is how do I keep those elements flexible? The most recent scenario where I stumbled upon this problem is when I tried using a ListView with an interior GridView. From my understanding GridView doesn't support declaring GridView columns with a width percentage and only use a fixed Width value. What is a work-around for this? Does it have to be this way? I would really like to make my UI as flexible as possible. Right now the fixed widths are screwing me over because I'm designing a UI for a 50" 2160p screen. However, my screen on which I'm designing on is much smaller (13" 1080p) and hence the elements get scaled out of existence and I can't really use it. Here's an example of what I'm looking for or what would be the ideal scenario.
Current scenario
<ListView ItemsSource="{Binding NotApprovedChanges}" Margin="40 90 40 40" FontSize="26" Name="nonApprovedChangesList">
<ListView.View>
<GridView>
<GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="ID" Width="150" DisplayMemberBinding="{Binding Id}" />
<GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="Requester" Width="200" DisplayMemberBinding="{Binding Requester}" />
<GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="Date" Width="250" DisplayMemberBinding="{Binding Date}" />
</GridView>
</ListView.View>
</ListView>
What I'm looking for
<ListView ItemsSource="{Binding NotApprovedChanges}" Margin="40 90 40 40" FontSize="26" Name="nonApprovedChangesList">
<ListView.View>
<GridView>
<GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="ID" Width="*" DisplayMemberBinding="{Binding Id}" />
<GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="Requester" Width="2*" DisplayMemberBinding="{Binding Requester}" />
<GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="Date" Width="*" DisplayMemberBinding="{Binding Date}" />
</GridView>
</ListView.View>
</ListView>
or
<ListView ItemsSource="{Binding NotApprovedChanges}" Margin="40 90 40 40" FontSize="26" Name="nonApprovedChangesList">
<ListView.View>
<GridView>
<GridView.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2* />
<ColumnDefinition Width="*" />
</GridView.ColumnDefinitions>
<GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="ID" GridView.Column="0" DisplayMemberBinding="{Binding Id}" />
<GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="Requester" GridView.Column="1" DisplayMemberBinding="{Binding Requester}" />
<GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="Date" GridView.Column="2" DisplayMemberBinding="{Binding Date}" />
</GridView>
</ListView.View>
</ListView>
hi i have listview how i can hide Id column? this is my listview xaml:
<ListView FlowDirection="RightToLeft" Grid.Row="1" SelectionMode="Single" Name="dgv" Margin="12,0,10,-81">
<ListView.View>
<GridView>
<GridViewColumn Header="آموزشگاه" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="مدیر" DisplayMemberBinding="{Binding Admin}" />
<GridViewColumn Header="پایه" DisplayMemberBinding="{Binding Base}" />
<GridViewColumn Header="سال تحصیلی" DisplayMemberBinding="{Binding Year}" />
<GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}"/>
</GridView>
</ListView.View>
</ListView>
Accepted solution/workaround in this case is setting the Width to 0.
How do I wrap text in a Grid?
In MainWindow.xaml
<Grid>
<ListView Margin="10" Name="Users" >
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="300" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Age" Width="200" DisplayMemberBinding="{Binding Age}" />
</GridView>
</ListView.View>
</ListView>
</Grid>
In MainWindow.xaml.cs
public ObservableCollection<User> items = new ObservableCollection<User>();
items.Add(new User() { Name = "John", Age = 42 });
Users.ItemsSource = items;
You should create DataTemplate for the GridViewColumn and place TextBlock. Then it is possible to use TextWrapping property. Work example:
<ListView Name="Users">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="385">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding Name}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Age" Width="385">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding Age}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I have tried to bind the data into the ListView control:
<ListView Margin="8" Height="400" Width="650"
ItemsSource="{Binding Path=MyData}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="Auto"
DisplayMemberBinding="Binding Path=ID}" >
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=Name}"
Header="Name" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Price}"
Header="Price" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Author}"
Header="Author" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=Catalog}"
Header="Catalog" Width="100"/>
</GridView>
</ListView.View>
</ListView>
ObservableCollection<TableInfo> _MyData
public ObservableCollection<TableInfo> MyData{ get; set; }
However, it's not display anything in the window but MyData is an ObservableCollection. How do I bind the data?
Tanya,
If you set your view model properly and if you're sure that your MyData collection is not null or empty, try to remove the "Path" keywords from your xaml:
<ListView Margin="8" Height="400" Width="650"
ItemsSource="{Binding Path=MyData}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="Auto"
DisplayMemberBinding="{Binding ID}" >
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Name}"
Header="Name" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Price}"
Header="Price" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Author}"
Header="Author" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Catalog}"
Header="Catalog" Width="100"/>
</GridView>
</ListView.View>
</ListView>
If this doesn't help, check the debug output and post it, we will definitely figure something out.
Your XAML looks fine to me.
Make sure you are setting the DataContext correctly.
yourView.DataContext = YouViewModel;
When the Binding is first evaluated, it may (depending on your code) find null. It does not get notified if you later set it to something sensible.
Try to make sure that you create the ObservableCollection in your classes costructor and not overwrite it somewhere else. You could alternativly implement INotifyPropertyChanged and raise a PropertyChanged event on te MyData setter.
In the following code:
<ListView Grid.Row="1" Margin="10" x:Name="lstRole" Grid.ColumnSpan="3"
MouseDoubleClick="lstRole_MouseDoubleClick">
<ListView.View>
<GridView>
<GridViewColumn Header="Role ID" DisplayMemberBinding="{Binding ID}" />
<GridViewColumn Header="Role Name" DisplayMemberBinding="{Binding Name}" />
</GridView>
</ListView.View>
</ListView>
The result is:
I don't know where is the third column come from !!
The question is: How to make the second column "RoleName" extends on the width of the ListView?
I used RangeColumn control in one of my applications and it worked very well.
You can use this control to set something like this
<GridView>
<GridViewColumn Header="Role ID" DisplayMemberBinding="{Binding ID}" />
<GridViewColumn Header="Role Name" ctrl:RangeColumn.IsFillColumn="true" DisplayMemberBinding="{Binding Name}" />
</GridView>