Get the selected value - c#

I am attempting to pull information from my listview but cannot seem to select a specific dataset. When pulling information from this I always get the entire contents back but can never read just one set.
I will be pulling the row data as:
chartViewList2.SelectedItem
I added information to the list view via
private void getServices(string ComputerName)
{
chartListView2.Items.Clear();
ServiceController[] services = ServiceController.GetServices(ComputerName);
foreach (ServiceController service in services)
{
chartListView2.Items.Add(new { Service = service.ServiceName, Status = service.Status, Desc = service.DisplayName });
}
}
List View XML:
ListView x:Name="chartListView2" Margin="12,59,46,6"
GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler2">
<ListView.View>
<GridView>
<GridViewColumn Header="Service" DisplayMemberBinding="{Binding Service}" Width="100"/>
<GridViewColumn Header="Status" DisplayMemberBinding="{Binding Status}" Width="60"/>
<GridViewColumn Header="Desc" DisplayMemberBinding="{Binding Desc}" Width="190"/>
</GridView>
</ListView.View>
</ListView>
All I want to get from this is the Service name field back.
Any help will be appreciated!

Reflection may help here.
var item = chartViewList2.SelectedItem;
var type = item.GetType();
var propertyInfo = type.GetProperty("Service");
var value = propertyInfo.GetValue(item, null);
Then you will have a value of Service field in 'value' variable.
Since .NET 4 and dynamic keyword even shorter way exists:
dynamic item = chartViewList2.SelectedItem;
dynamic propertyValue = item.Service;

If you are binding your ListView to a List<TypedObject> then you can do this:
var item = chartViewList2.SelectedItem as TypedObject

You can set the ListView SelectedvaluePath to Service and bind to your model or access using the ListView SelectedValue.
Example:
<ListView x:Name="chartListView2" SelectedValuePath="Service" SelectedValue="{Binding SelectedServiceName}" >

Related

C# Listview DisplayMemberBinding shows "wrong" value

In my WPF app I have a Listview with a couple columns and one column with a checkbox inside.
The xaml is as follows:
<ListView x:Name="listviewImported">
<ListView.View>
<GridView>
<GridViewColumn Header="Check" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
/*This line may be the prob.*/ <CheckBox IsChecked="{Binding MarkedForCheck}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Pos." Width="75" DisplayMemberBinding="{Binding PositionAsString}" />
<GridViewColumn Header="Value" Width="175" DisplayMemberBinding="{Binding ImportValue}" />
<GridViewColumn Header="Type" Width="175" DisplayMemberBinding="{Binding ImportValueTypeDescription}" />
</GridView>
</ListView.View>
</ListView>
The ItemSource is assigned like this:
listviewImported.ItemsSource = _catalog.ImportedList;
The ImportedList in the _catalog is of Type ImportedElem:
private List<ImportedElem> _importedList = new List<ImportedElem>();
This is the ImportedElem class:
public class ImportedElem : BaseElem {
public ImportedElem(int Position, string ImportValue) : base(Position, ImportValue) {
}
//MARKED FOR CHECK
public bool MarkedForCheck = true;
}
This is the problem:
When I add an ImportedElem to the List, then the Listview will update and the columns "Pos.", "Value" and "Type" contain the correct Data. However, the Column with the checkbox ("Check") always shows a nonchecked Checkbox after adding it to the List. The Data is correct, the column just shows the wrong Data. I can modify the checkbox in the list and it will update the Data, that is good. But the List should contain the correct Data right after adding the Element to the list, wich it is not doing. It would be very interesting to know why 3 columns are correct and the checkbox doesn't work.
change public bool MarkedForCheck = true; TO public bool MarkedForCheck {get;set;}

copy listview subitems to variable

I've already search for any solutions but I just couldn't find one. I've found several post in several websites/forum that discusses my problem, but I want a very simple solution.
while (SQLDataReader.Read())
{
var view = new GridView();
view.Columns.Add(new GridViewColumn { Header = "User", DisplayMemberBinding = new Binding("User") });
view.Columns.Add(new GridViewColumn { Header = "hostNamedb", DisplayMemberBinding = new Binding("hostNamedb") });
view.Columns.Add(new GridViewColumn { Header = "fullName", DisplayMemberBinding = new Binding("fullName") });
view.Columns.Add(new GridViewColumn { Header = "location", DisplayMemberBinding = new Binding("location") });
view.Columns.Add(new GridViewColumn { Header = "department", DisplayMemberBinding = new Binding("department") });
view.Columns.Add(new GridViewColumn { Header = "position", DisplayMemberBinding = new Binding("postion") });
view.Columns.Add(new GridViewColumn { Header = "message", DisplayMemberBinding = new Binding("message") });
view.Columns.Add(new GridViewColumn { Header = "status", DisplayMemberBinding = new Binding("status") });
view.Columns.Add(new GridViewColumn { Header = "ip", DisplayMemberBinding = new Binding("ip") });
ListView2.View = view;
ListView2.Items.Add(new
{
User = SQLDataReader["User"].ToString(),
hostNamedb = SQLDataReader["hostNamedb"].ToString(),
fullName = SQLDataReader["fullName"].ToString(),
location = SQLDataReader["location"].ToString(),
department = SQLDataReader["department"].ToString(),
position = SQLDataReader["position"].ToString(),
message = SQLDataReader["message"].ToString(),
status = SQLDataReader["status"].ToString(),
ip = SQLDataReader["ip"].ToString(),
});
}
userName_click = System.Convert.ToString(ListView2.Items[var2].User.Text.ToString());
hostName_click = System.Convert.ToString(ListView2.Items[var2].hostNamedb.Text.ToString());
fullName_form = System.Convert.ToString(ListView2.Items[var2].SubItems[2].Text.ToString());
location_form = System.Convert.ToString(ListView2.Items[var2].SubItems[3].Text.ToString());
department_form = System.Convert.ToString(ListView2.Items[var2].SubItems[4].Text.ToString());
position_form = System.Convert.ToString(ListView2.Items[var2].SubItems[5].Text.ToString());
message_Form = System.Convert.ToString(ListView2.Items[var2].SubItems[6].Text.ToString());
status_form = System.Convert.ToString(ListView2.Items[var2].SubItems[7].Text.ToString());
id_form = System.Convert.ToString(ListView2.Items[var2].SubItems[8].Text.ToString());
userIP_click = System.Convert.ToString(ListView2.Items[var2].SubItems[9].Text.ToString());
Basically, the codes here works like this: the program will get the data from my database and then add them to my Listview2.
(Also, can someone check if my adding items to listview2 will work? I can't run the program right now because I really have to do lots of re-coding. I'm migrating from VB.NET to C# WPF).
Going on: each variable, like userName_click will have the data from the
listview2-row-VAR2 with columns 0 to 8.
I tried replacing the subitems[n] with binding names like User from -->
(new binding("user")) but it didn't work.
by the way, here is my XAML code in listview2.
<ListView x:Name="ListView2" HorizontalAlignment="Left" Height="34" Margin="-10,446,-22,-50" VerticalAlignment="Top" Width="702" Grid.ColumnSpan="3" ClipToBounds="True">
<ListView.View>
<GridView ColumnHeaderContainerStyle="{DynamicResource CustomHeaderStyle}">
<l:FixedWidthColumn Header="username" DisplayMemberBinding="{Binding User}" FixedWidth="65"/>
<l:FixedWidthColumn Header="Host Name" DisplayMemberBinding="{Binding hostNamedb}" FixedWidth="65"/>
<l:FixedWidthColumn Header="fullname" DisplayMemberBinding="{Binding fullName}" FixedWidth="85"/>
<l:FixedWidthColumn Header="location" DisplayMemberBinding="{Binding location}" FixedWidth="65"/>
<l:FixedWidthColumn Header="department" DisplayMemberBinding="{Binding department}" FixedWidth="65"/>
<l:FixedWidthColumn Header="position" DisplayMemberBinding="{Binding position}" FixedWidth="65"/>
<l:FixedWidthColumn Header="message" DisplayMemberBinding="{Binding message}" FixedWidth="65"/>
<l:FixedWidthColumn Header="status" DisplayMemberBinding="{Binding status}" FixedWidth="65"/>
<l:FixedWidthColumn Header="id" DisplayMemberBinding="{Binding id}" FixedWidth="65"/>
<l:FixedWidthColumn Header="ip" DisplayMemberBinding="{Binding ip}" FixedWidth="65"/>
</GridView>
</ListView.View>
</ListView>
Your solution is not following, but since you know about binding I think you already know that. I can not help you making your existing code work, but instead suggest the following: Use an observable collection to hold your DB-Objects with fields like user, hostNamedb...
public DbEntry(){
user = SQLDataReader["User"].ToString();
hostNamedb = SQLDataReader["hostNamedb"].ToString();
fullName = SQLDataReader["fullName"].ToString();
location = SQLDataReader["location"].ToString();
...
}
These will fill your observable collection. Next you bind to that collection via ItemsSource in your XAML.
<ListView ItemsSource="{Binding DBObjectsCollection}">
Filling your variables with data is now only a matter of specifiying the index of the "row" from which to get the data, and getting the right field or property, e.g.
userName_click = DBObjectsCollection[2].user;
Mind you, this code will not work. This is only meant to be a basic pointer to how to solve your problem in WPF. There is already tons on information on WPF, but feel free to ask questions, should any arise.

How do I add a row to my list view?

I can't seem to get this to work. Anyone have any ideas why?
Here is the markup:
<ListView Width="210" Height="83" Margin="0 0 5 0" Name="FiltersListView">
<ListView.View>
<GridView>
<GridViewColumn Header="Column" Width="Auto" DisplayMemberBinding="{Binding FilterColumn}"></GridViewColumn>
<GridViewColumn Header="Rule" Width="Auto" DisplayMemberBinding="{Binding FilterRule}"></GridViewColumn>
<GridViewColumn Header="String" Width="Auto" DisplayMemberBinding="{Binding FilterString}"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Here is the window initializer:
public SelectionWindow()
{
InitializeComponent();
rows = new List<Row>();
// Create a new binding object and set the binding of this list view to it.
Binding myBinding = new Binding();
myBinding.Source = rows;
FiltersListView.SetBinding(ItemsControl.ItemsSourceProperty, myBinding);
}
Here is my rows object and class:
List<Row> rows;
public class Row
{
public string FilterColumn;
public string FilterRule;
public string FilterString;
}
But when I click this button, I don't see it getting added to the list:
private void AddButtonClick(object sender, RoutedEventArgs e)
{
Console.WriteLine("Adding row.");
rows.Add(new Row { FilterColumn = "1", FilterRule = "2", FilterString = "3" });
Console.WriteLine("Row added.");
}
This is because List<int> doesn't implement INotifyCollectionChanged, so the control doesn't know that the list has actually been updated.
Try to make rows an ObservableColelction<Row>.
Edit: as the OP mentioned, the other problem (empty rows) was due to using fields, not properties, on Row.

Dynamically Adding Items To a WPF List View

I am trying to programatically add items to a ListView in WPF. I have done a lot of reading (including some questions here) and thought I was doing it correctly but the items aren't showing up. As I understand it I create the ListViewe and bind it to a data source, in this case an ObservableCollection. I have verified the ObservableCollection is getting items added to it, but they aren't getting displayed on the ListView. If it matters, the ListView is already instantiated by the time I run the LINQ query and attempt to add items to it.
Here is the XAML that defines the list view:
<TabPanel Name="ResultsTab" Height="200" Width ="500" DockPanel.Dock="Top" HorizontalAlignment="Left">
<TabItem Name="Default_Tab" Header="Default">
<ListView Name="DefaultListView" ItemsSource="Binding FCPortCollection">
<ListView.View>
<GridView x:Name="DefaultGridView">
<GridViewColumn Width="Auto" Header="FC Port" DisplayMemberBinding="{Binding Path=FCPort}" />
<GridViewColumn Width="Auto" Header="WWPN" DisplayMemberBinding="{Binding Path=WWPN}"/>
<GridViewColumn Width="Auto" Header="FCID" DisplayMemberBinding="{Binding Path=FCID}" />
<GridViewColumn Width="Auto" Header="SwitchName" DisplayMemberBinding="{Binding Path=SwitchName}">
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</TabItem>
And here is the code that is supposed to load it.
public class PortResult
{
public string SwitchName;
public string FCPort;
public string FCID;
public string WWPN;
public PortResult(string name, FCPort port)
{
SwitchName = name;
FCPort = String.Format("fc{0}/{1}", port.SlotNum, port.PortNum);
WWPN = port.WWPNList[0].WWPNValue;
FCID = port.WWPNList[0].FCIDValue;
}
}
ObservableCollection<PortResult> FCPortCollection = new ObservableCollection<PortResult>();
// results is an IEnumerable collection of FCPort result from a LINQ query that has been turned into a Dictionary
foreach (KeyValuePair<string, List<FCPort>> resultspair in results)
{
foreach (FCPort port in resultspair.Value)
{
// create a new PortResult and add it to the ObservableCollection
PortResult pr = new PortResult(resultspair.Key, port);
FCPortCollection.Add(pr);
}
}
There are several problems in the code you posted:
The binding syntax for your ItemsSource is missing the {} braces - it needs to be ItemsSource="{Binding FCPortCollection}"
You can only bind to properties, however you only expose fields in your PortResult class. Change those fields to be properties.
Also make sure the DataContext of the ListView is set to the object which contains the FCPortCollection. Also make sure the collection is a property of the object and not a field (same reason as point 2. above).
This:
ItemsSource="Binding FCPortCollection"
Is not a binding, you forgot the braces {} and hence assigned a char[] as ItemsSource instead.

WPF ListView Binding + Error

I am getting an exception "Object reference not set to an instance of an object." on the "songs.DataContext =" line. If I add songs = new ListView(); before it my listview is empty even though the list of audiofiles is not
XAML:
<ListView Height="Auto" HorizontalAlignment="Center" ItemsSource="{Binding}"
VerticalAlignment="Center" Name="songList" Width="Auto" MinHeight="300" MinWidth="600">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" Header="Title" DisplayMemberBinding="{Binding Path=Title}" />
<GridViewColumn Width="Auto" Header="Artist" DisplayMemberBinding="{Binding Path=Artist}" />
<GridViewColumn Width="Auto" Header="Album" />
<GridViewColumn Width="Auto" Header="Length" />
</GridView>
</ListView.View>
</ListView>
C#
public struct AudioFile
{
public String Artist;
public String Title;
public String Album;
public String fileLocation;
public String Length;
}
//...
private List<AudioFile> songs = new List<AudioFile>();
//code that adds to array
songList.DataContext = songs;
I suspect your code to be in the constructor, in a place where songList is not yet created.
//...
private List<AudioFile> songs = new List<AudioFile>();
//code that adds to array
songList.DataContext = songs;
Try to move it in the Loaded event instead.
Your songs are clearly instatiated, but what about the songList?
I think you may be trying to set songList.ItemsSource = list in your constructor and obviously the object is not built yet.
In your UI classes, best place to initialize will be only in Loaded event or after InitializeComponent method.
Even better approach will be to use MVVM.
Are you writing this code -
//...
private List<AudioFile> songs = new List<AudioFile>();
//code that adds to array
songList.DataContext = songs;
before IniitializeComponent() method is called for a view?? Can you provide a bit more of insight regarding your code placement that will help in understanding the situation better.
And just a suggestion, not related though. I would say use class instead of structure objects because WPF data binding considers only properties, not fields. Definitely, this is not a cause of an error though.

Categories

Resources