Unable to bind the collection to Listview in WPF application? - c#

I am developing a WPF application where i can read some properties from the windows services list which are currently running on my system.I am able to read the properties of a particular service and passing to a collection which in turn show up in my UI under a Listview.
I want the same scenario to be used for list of services .i.e.i am trying in the following way..but i am not sure where did i miss the point...
Here is my code
foreach (string serviceName in sList)
{
ServiceController controller = new ServiceController(serviceName);
StatusCollection.Add (new StatusData
{
Name = name,
Status = status
});
lvStatus.DataContext = StatusCollection;
lvStatus.ItemsSource = StatusCollection;
}
<ListView Height="166" HorizontalAlignment="Left" Margin="23,0,0,0" Name="lvStatus" VerticalAlignment="Top" Width="264" >
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"></GridViewColumn>
<GridViewColumn Header="Status" DisplayMemberBinding="{Binding Status}"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>

Remove the DataContext line of code.
If you set your ItemsSource in the code behind make sure you do it before InitializeComponent is called. If not, you will need to refresh your Items collection.
However, I would setup a View Model for your Window or Control which implements INotifyPropertyChanged. Create your collection as an ObservableCollection and bind to it in the XAML:
<ListView ... ItemsSource={Binding Path=ServiceList}>
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}" />
<GridViewColumn Header="Status" DisplayMemberBinding="{Binding Path=Status}" />
</GridView>
</ListView.View>
</ListView>
Let me know if you need an example of using a View Model.

Related

How to bind ObservableCollection to the ListView in a UserControl?

I have the following xaml file:
<Page ...>
<Grid>
<ListView ItemsSource="{Binding MissingValues}">
<ListView.View>
<GridView AllowsColumnReorder="true" ColumnHeaderToolTip="Information on Missing Values">
<GridViewColumn DisplayMemberBinding="{Binding Path=Element.Name}" Header="Element" Width="100" />
<GridViewColumn DisplayMemberBinding="{Binding Path=Description}" Header="Description" />
</GridView>
</ListView.View>
</ListView>
</Grid>
Code behind is only:
DataContext = new MyViewModel();
And MyViewModel has public ObservableCollection<MissingValue> MissingValues initialized in the constructor. On the button click, items are added to this property and everything works as exptected.
Since the xaml file became too big, i wanted to make it smaller and easier to manage by extracting this ListView in a UserControl called MissingValuesListView and invoking it using the following code:
<local:MissingValuesListView></local:MissingValuesListView>
However, the list is no longer updated when the new elements are added.
MissingValuesListView's code behind contains only DataContext = new MyViewModel();.
I don't think it's of any relevance (since the code works when part of the main xaml file, but not when moved to UserControl), but both MyViewModel and MissingValue implment INotifyPropertyChanged.
My question is why is this not working? I assume i'm missing some code or some binding, but i failed to find out what. Any help is highly appreciated!
MissingValuesListView's code behind contains only DataContext = new MyViewModel();.
It shouldn't. Try to remove this line. You should simply copy the following XAML into MissingValuesListView.xaml and replace it with <local:MissingValuesListView /> in the current XAML file:
<ListView ItemsSource="{Binding MissingValues}">
<ListView.View>
<GridView AllowsColumnReorder="true" ColumnHeaderToolTip="Information on Missing Values">
<GridViewColumn DisplayMemberBinding="{Binding Path=Element.Name}" Header="Element" Width="100" />
<GridViewColumn DisplayMemberBinding="{Binding Path=Description}" Header="Description" />
</GridView>
</ListView.View>
</ListView>
If you do this, the UserControl will inherit the DataContext where the MissingValues property is defined from its parent element and the binding should work just like before.

How do I populate listview in 2 columns from 2 arrays in WPF c#

I have a listview item
(XAML)
<ListView Name="myListView" BorderThickness="2,2,2,2" Margin="12,27,428,12">
<ListView.View>
<GridView>
<GridViewColumn Width="150" Header="Column1" DisplayMemberBinding="{Binding Test1}"/>
<GridViewColumn Width="150" Header="Column2" DisplayMemberBinding="{Binding Test2}"/>
</GridView>
</ListView.View>
<ListViewItem>
</ListViewItem>
</ListView>
And want to fill it with 2 different arrays
string[] ApplicationNames
string[] ClassNames
but I'm having difficulty doing so. Can anyone point me in the right direction?
I'm using WPF
The answer to your question might be found here.
P.S. If you are developing UI in XAML, you are developing a WPF Application, not Winforms. Winforms applications are created by choosing Windows Forms Application when choosing the project type in Visual Studio.
XAML:
<ListView Name="ResultListView">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" DisplayMemberBinding="{Binding ApplicationName }" Header="File" />
<GridViewColumn Width="Auto" DisplayMemberBinding="{Binding ClassName }" Header="Location" />
</GridView>
</ListView.View>
</ListView>
MyObject.cs
class MyObject
{
public string ApplicationName { get; set; }
public string ClassName { get; set; }
}
ObservableCollection<MyObject> results = new ObservableCollection<MyObject>();
//Populate some data into results here
ResultListView.ItemsSource =results;

Binding a ListView to an ObservableCollection of ArrayList items without named properties

Firstly:
<ListView Height="259" HorizontalAlignment="Left" Margin="7,6,0,0" Name="dataListView" VerticalAlignment="Top" Width="899">
<ListView.View>
<GridView>
<GridViewColumn Width="240" Header="Test" />
<GridViewColumn Width="50" Header="Result" />
<GridViewColumn Header="Column 3" />
</GridView>
</ListView.View>
</ListView>
is the definition in my XAML file.
Then when a test starts, I run:
dataListView.ItemsSource = tr.TestResultCollection;
In TestRunner.cs, I have created the Observable Collection of ArrayLists as such:
ObservableCollection<ArrayList> _testResultCollection = new ObservableCollection<ArrayList>();
and publicly refer to them as such:
public ObservableCollection<ArrayList> TestResultCollection
{ get { return _testResultCollection; } }
Finally when I add to the collection, I use :
_testResultCollection.Add(SummaryVerificationTestCase1(dbs, dbd));
which adds an ArrayList to the collection. (Yes, a collection of ArrayLists, I know...)
However, what gets displayed in each Column is (Collection), (Collection, (Collection).
I see why. However, I'm not entirely certain what the neatest way around is. Normally in each GridViewColumn you give a binding like:
DisplayMemberBinding="{Binding TestResult}"
But the ArrayList doesn't have named components, just indices (0-2).
Is there a way to bind each column to the individual indices? Or have I missed something simple already?
Specify an index in the binding path:
<GridViewColumn Width="240" Header="Test" DisplayMemberBinding="{Binding Path=[0]}"/>
<GridViewColumn Width="50" Header="Result" DisplayMemberBinding="{Binding Path=[1]}"/>
<GridViewColumn Header="Column 3" DisplayMemberBinding="{Binding Path=[2]}"/>

How to bind a ListView to an ObservableCollection<KeyValuePair<int,object>> inside a ViewModel in WPF?

Something like this:
public class EffectViewModel
{
public string Name ...
ObservableCollection<KeyValuePair<int,object>> settings
public ObservableCollection<KeyValuePair<int,object>> Settings
{
get {return this.settings;}
set
{
this.settings = value;
this.RaisePropertyChanged ( "Settings" );
}
}
}
Right now I am trying to bind it like this:
EffectWindowViewModel.Effects is of type ObservableCollection<EffectViewModel>.
<ListView Width="1000"
Height="600"
ItemsSource="{Binding EffectWindowViewModel.Effects}">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Key}"
Header="Name" />
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Value}"
Header="Value" />
</GridView>
</ListView.View>
</ListView>
But I don't know how to specify .Settings property.
Any ideas?
your actual binding will not work cause EffectViewModel has no key and Value Property. i really dont know what your listview should display. if you want a list of EffectViewModels then the Itemssource is right. if you want further for each EffectViewModel to display the settings. then you need somekind of itemsscontrol with Itemssource={Binding Settings}. this itemsscontrol of course will need a itemsstemplate with your Key and Value.
i have no VS here atm, but your GridViewColumn needs a kind of CellTemplate. and this template should consist of a itemscontrol. because you have 2collections!
this code is probably not right but should take you in the right direction
<ListView Width="1000"
Height="600"
ItemsSource="{Binding EffectWindowViewModel.Effects}">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Settings}">
<GridViewColumn.CellTemplate>
<DataTemplatex:Key="myCell4Settings">
<ListView ItemsSource="{Binding.}">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Key}"
Header="Name" />
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Value}"
Header="Value" />
</GridView>
</ListView.View>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</ListView>
</DataTemplate>
</GridView>
</ListView.View>
btw you could also use 2 lists independent. one parent Combobox or listbox (x:Name=parent) with itemssource=EffectWindowViewModel.Effects and a second ListView like you have, with the itemssource binding:
ItemsSource="{Binding ElementName=parent, Path=SelectedItem.Settings}"
You could try:
ItemsSource="{Binding ElementName=Settings, Path=EffectWindowViewModel.Effects}"

How do I edit a usercontrol's subcontrol template in xaml when adding the usercontrol to a window?

I have a user control that contains a listview. In the windows where I use this usercontrol, I want to be able to do something like what is shown below where I set the template for a control within the user control.
<ct:AutoCompleteComboBox
SelectedValue="{Binding Path=SelectedCountry}"
ItemsSource="{Binding Path=CountryList}" >
<ct:AutoCompleteComboBox.DropDownList >
<ListView
Background="Blue"
MinWidth="150"
MaxHeight="200">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header=" Name" DisplayMemberBinding="{Binding Name}" >
</GridViewColumn>
<GridViewColumn Header="Desc" DisplayMemberBinding="{Binding Description}" >
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</ct:AutoCompleteComboBox.DropDownList>
</ct:AutoCompleteComboBox>
How do I go about doing this? I found that if I made AutoCompleteComboBox.DropDownList a dependency property, then the code would compile. However, this DropDownList property is not actually added to my control (it is added to the parent container of ct:AutoCompleteComboBox).
Any idea of the proper way to do this?
Thanks in advance
Bind subcontrol's property you want to be available outside to the property you created in the container control.

Categories

Resources