I am writing some programm where is possible to select device and later configure it. I implemented ListView where all device are listed. I like that first device is selected by default. How to do that? I try several solution found on StackOverflow and over Google but without luck.
Here is my code in XAML:
<ListView Name="lvdevices" Grid.Row="1" Margin="2" ItemsSource="{Binding devicelist}" SelectionMode="Single" SelectedItem="{Binding SelectedDevice}" DataContext="{Binding }">
<ListView.View>
<GridView x:Name="gridDevices">
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding ID}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}}, Path=IsSelected}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn x:Name="DeviceId" Header="DeviceId" DisplayMemberBinding="{Binding DeviceId}" Width="50"/>
<GridViewColumn x:Name="NameId" Header="NameId" DisplayMemberBinding="{Binding NameId}" Width="100"/>
<GridViewColumn x:Name="ManufacturerId" Header="ManufacturerId" DisplayMemberBinding="{Binding ManufacturerId}" Width="150"/>
</GridView>
</ListView.View>
</ListView>
I dont know how to implement that first item is selected by default when is connected. It is also possibility that no device will found, what then? Please for help! If and question please ask.
When you populate your devicelist, you can set the SelectedDevice to be the first item in the device list, or null if there is nothing in the list.
using System.Linq;
...
SelectedDevice = devicelist.FirstOrDefault();
Assuming that SelectedDevice implements INotifyPropertyChanged, this should then select the first item on your view.
In your ViewModel, you just need to set your SelectedDevice to the first item (and of course trigger a OnPropertyChanged)
Related
I want to check all text boxes on the basis of if the check box is checked. But I don't know how to access all check boxes one by one? I bound it with ApprovalStatus which is of boolean type. Can any one help me to have code in C#?
<CheckBox Content="Check All" Height="16" HorizontalAlignment="Left" Margin="9,193,0,0" Name="Tab2CheckAll" VerticalAlignment="Top" Width="77" Click="Tab2CheckAll_Click"/>
<ListView Height="213" HorizontalAlignment="Left" Margin="9,215,0,0" Name="Tab2EmployeeEffortList" VerticalAlignment="Top" Width="771" AllowDrop="True" IsTextSearchEnabled="True">
<ListView.View>
<GridView>
<GridViewColumn Header="Approved" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox CommandParameter="{Binding}" IsChecked="{Binding ApprovalStatus}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
You need not to access individual checkBoxes. CheckBox is already bounded to property set that instead.
Loop over ItemsSource of ListView and set ApprovalStatus to true for all items in the collection. As long as your underlying source class is implementing INotifyPropertyChanged, it will work fine.
I have 2 ObservableCollection lists, which we can call A and B, then I have a GridView that I want to bind to list A and a ComboBox INSIDE that GridView, that I want to bind to list B.
I've set the ItemsSource property of the GridView by code: gridview.ItemsSource=A (and it works!). About the ComboBox its instance it is not available by code, I suppose because its definition it is enclosed between the DataTemplate tags; so I wonder how to bind the combo to list B, either by code or by XAML.
Follows the XAML code:
<ListView Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="lstReplacements" VerticalAlignment="Stretch">
<ListView.View>
<GridView>
<GridViewColumn HeaderContainerStyle="{StaticResource MyHeaderStyle}" Header="Wrong text" DisplayMemberBinding="{Binding Word}"/>
<GridViewColumn HeaderContainerStyle="{StaticResource MyHeaderStyle}" Header="Replacement" Width="60" DisplayMemberBinding="{Binding Replacement}" />
<GridViewColumn HeaderContainerStyle="{StaticResource MyHeaderStyle}" Header="Type" Width="30">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{??????}" DisplayMemberPath="??????" Grid.Row="1" Grid.Column="0" Name="cmbCorrectionType" Width="75" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Thanks in advance for the support!
Chris
I assume this control is in UserControl and you have set DataContext of that UserControl to the class instance where your both collections CollectionA and CollectionB resides.
You can then bind using RelativeSource:
<ComboBox ItemsSource="{Binding DataContext.CollectionB,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=UserControl}}"/>
Also you can set DataContext of ListView to the class instance and all you need to do is change AncestorType to ListView in place of UserControl in above binding.
I'm trying to switch over to WPF from Winform and so far it's a pain.
Anyway, I am trying to get this binding thing to work using DataTemplate.
I have a class:
public class TranslatorListItem
{
public string Item { get; set; }
public string OriginalMessage { get; set; }
public string TranslatedMessage { get; set; }
public string Sector { get; set; }
}
Items are added like this:
TranslatorListItem TLI = new TranslatorListItem();
TranslatorLVI.Items.Add(TLI);
My XAML DataTemplate:
<DataTemplate x:Key="MyDataTemplate">
<Border BorderBrush="#FFA4D5E5" BorderThickness="1,1,0,0" Margin="6">
<StackPanel Margin="6,2,6,2">
<TextBox Text="{Binding}" TextWrapping="Wrap" BorderThickness="0" BorderBrush="#00000000" />
</StackPanel>
</Border>
</DataTemplate>
This is how I'm trying to bind the data but it's returning this error: "Two-way binding requires Path or XPath."
<ListView Margin="23,224,27,54" Name="TranslatorLVI" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch"
ItemContainerStyle="{StaticResource MyItemContainerStyle}">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="Item" DisplayMemberBinding="{Binding Path=Item}" CellTemplate="{StaticResource MyDataTemplate}" />
<GridViewColumn Header="Original Message" Width="300" CellTemplate="{StaticResource MyDataTemplate}" />
<GridViewColumn Header="Translated Message" DisplayMemberBinding="{Binding Path=TranslatedMessage}" CellTemplate="{StaticResource MyDataTemplate}" />
<GridViewColumn Header="Sector" DisplayMemberBinding="{Binding Path=Sector}" />
</GridView>
</ListView.View>
</ListView>
I need TranslatedMessage binding to be editable. So that field wont be Read-Only.
I heard I may need to set Two-way binding, but I am not sure how to do so.
Any help is appreciated.
Thanks!
I'm trying to switch over to WPF from Winform and so far it's a pain.
No, it's not. WPF is the best UI Framework in the history of mankind. winforms (or anything else) can't even be compared with it.
Your problem is you're trying to use a winforms approach in WPF and you fail.
WPF does not support developers with a winforms mentality.
All the horrible code behind hacks you're used to from winforms are completely unneeded in WPF.
Please read Rachel's Excellent Answer (and linked blog posts) about the mindshift needed when upgrading from winforms to WPF.
As mentioned in #JasRaj's answer, you're missing a DisplayMemberBinding in this case. I tested your code and added that, like this:
<GridViewColumn Header="Original Message"
DisplayMemberBinding="{Binding OriginalMessage}"
Width="300"/>
And it worked perfectly.
After a second read to your question I realized you wanted to make one of these columns editable.
First of all I will say that while what you want can be achieved with a ListView, using a DataGrid is easier.
You need to remove the DisplayMemberBindings from the ListView in order to use a CellTemplate, and therefore you need to modify the template slightly:
<DataTemplate x:Key="MyDataTemplate">
<Border BorderBrush="#FFA4D5E5" BorderThickness="1,1,0,0" Margin="6">
<TextBox Text="{Binding TranslatedMessage}"
TextWrapping="Wrap"
BorderThickness="0"
BorderBrush="#00000000" />
</Border>
</DataTemplate>
I have placed a ListView and a DataGrid side by side so you can compare them:
Here is the XAML:
<UniformGrid Columns="2">
<ListView ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="Item" DisplayMemberBinding="{Binding Path=Item}"/>
<GridViewColumn Header="Original Message" DisplayMemberBinding="{Binding OriginalMessage}" Width="300"/>
<GridViewColumn Header="Translated Message" CellTemplate="{StaticResource MyDataTemplate}" />
<GridViewColumn Header="Sector"/>
</GridView>
</ListView.View>
</ListView>
<DataGrid ItemsSource="{Binding}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Item" Binding="{Binding Path=Item}" IsReadOnly="True"/>
<DataGridTextColumn Header="Original Message" Binding="{Binding OriginalMessage}" IsReadOnly="True" Width="300"/>
<DataGridTextColumn Header="Translated Message" Binding="{Binding TranslatedMessage}" />
<DataGridTextColumn Header="Sector" Binding="{Binding Sector}"/>
</DataGrid.Columns>
</DataGrid>
</UniformGrid>
Notice how the ListView requires DataTemplates in order to support edition, and is read-only by default, while the DataGrid is editable by default, does not need any special templats and requires that you add the IsReadOnly="True" to columns that are intended to be read-only.
Also, I noticed you're adding items manually to the ListView using procedural code. This is not desired in WPF. You must use an ObservableCollection<> and manipulate that collection, and let the WPF Binding engine update the UI for you.
It is recommended and desired that you Separate logic/data from UI in WPF.
If you need further clarification please let me know.
WPF Rocks.
Bind the second columns of Gridview with OriginalMessage property.
like :-
DisplayMemberBinding="{Binding Path=OriginalMessage}"
it should work.
In my opinion you dont fully use the datatemplate. you just use it to display one property;
In fact you can use a DataTemplate to display all data in thie class (TranslatorListItem);
such as this
<DataTemplate x:Key="MyDataTemplate">
<Border BorderBrush="#FFA4D5E5" BorderThickness="1,1,0,0" Margin="6">
<TextBox Text="{Binding Item}"
TextWrapping="Wrap"
BorderThickness="0"
BorderBrush="#00000000" />
<TextBox Text="{Binding TranslatedMessage}"
TextWrapping="Wrap"
BorderThickness="0"
BorderBrush="#00000000" />
( ..... follow up)
</Border>
</DataTemplate>
So your ListView can design like this:
<ListView ItemsSource="{Binding}" HorizontalContentAlignment="Stretch"
ItemTemplate="{StaticResource MyDataTemplate}">
</ListView>
How can I make a ListView imitate the ListView in Windows Explorer on the right side. Like how can I get icons in the ListView and get the arrows?
You can find the icons by using Google Image search. To create the ListView, you could do something like this is XAML:
<Grid>
<ListView ItemsSource="{Binding ListViewSource}">
<ListView.View>
<GridView>
<GridViewColumn Width="25">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Icon}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding FileName}" Width="250"/>
<GridViewColumn Header="Date Modified" DisplayMemberBinding="{Binding DateModified}" Width="100"/>
<GridViewColumn Header="Type" DisplayMemberBinding="{Binding FileType}" Width="100"/>
<GridViewColumn Header="Size" DisplayMemberBinding="{Binding FileSize}" Width="100"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
The next step is to create an ObservableCollection to hold all of the items in your list and call it ListViewSource. You can populate this collection with actual FileDirectory information, or your own kind of list. You'll then want to create your logic as to what happens when you doubleclick on an item. Since your question didn't specify to what detail you want the ListView to work, I'm going to stop there. Let us know if you want it to behave just like Windows Explorer, and we'll try to help you out.
I have set up a grid and bound it to a collection. I can edit the items in the collection through my grid and the changes get propagated to the collection. And, the GUI is showing everything in the collection at the time the ItemSource is set. But, I am programmatically changing some of the items in the collection (after the ItemSource is set) and these changes aren't reflected in the grid/GUI. Is there something else I need to do in order to get it to refresh. FYI, for the fields I want to edit (MoveToResource, ResourceKey, and Resource Type), I have set the mode to TwoWay. Below is my grid.
<ListView Name="lstXAMLStrings" Margin="5" Grid.Row="1">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Extract?">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Content="" IsChecked="{Binding Path=MoveToResource, Mode=TwoWay}" ></CheckBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Text">
<GridViewColumn.CellTemplate>
<DataTemplate>
<local:RichTextBlock RichText="{Binding Path=FormattedMatchedLines}" TextWrapping="Wrap" Width="650"></local:RichTextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Key Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=ResourceKey, Mode=TwoWay}" Width="150"></TextBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Resource Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource odp}}" SelectedItem="{Binding Path=Resource, Mode=TwoWay}"></ComboBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
Does your [view]model class implement INotifyPropertyChanged and fire the event whenever the property set accessor is used?
You need to make sure that the collection itself that you're databinding to is an observable collection (a class that implements the INotifyCollectionChanged interface). You might be able to alternatively roll your own class that implements INotifyCollectionChanged, but that's the only reason ObservableCollection exists so it could save you some time.
There's an msdn article on how to do it.
You need to make sure that your collection items implement INotifyPropertyChanged.
If each item you're changing programatically (correctly) implements that, your ListView/GridView will stay current.
This will work if you modify your collection items programatically, or in another screen.