C# WPF create checkboxes for each item in listview - c#

I have been searching for this on SO, but I have not found something that is doing exactly what I want. The below attached screenshot is what I want to create, this is done in VBA, but I am trying to create it in C# using WPF.
I am importing CSV files with the following structure:
"ID","NAME",CheckedINT
e.g.
"1662","BØRSTER",1 <-- 1 = checked, 0 = unchecked.
So when I import a file, it is displaying the information in the listview. However, I cannot manage to create that checkbox for each item/record. I have tried to create it in the XAML file.
If you need some of the code behind, e.g. to load the data into the listview, let me know.
I am fairly new to C#, so a thorough explanation would be very much appreciated (using VS15).
XAML:
<Window x:Class="CloneMacro.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CloneMacro"
mc:Ignorable="d"
Title="Clone Macro" Height="350" Width="592.045" Closed="MainWindow_Closed" Icon="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\copy.png">
<Grid Background="#FFDEDEDE" Margin="-1,0,1,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="71*"/>
<ColumnDefinition Width="399*"/>
<ColumnDefinition Width="114*"/>
</Grid.ColumnDefinitions>
<Button x:Name="cmdNew" HorizontalAlignment="Left" Margin="39,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="New" Grid.ColumnSpan="2" Click="cmdNew_Click">
<Image x:Name="imgNew" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\Generic_Document.png" RenderTransformOrigin="0.172,1.089"/>
</Button>
<Button x:Name="cmdOpen" HorizontalAlignment="Left" Margin="8,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Open" Grid.Column="1" Click="cmdOpen_Click">
<Image x:Name="imgOpen" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\folder_Open_32xLG.png"/>
</Button>
<Button x:Name="cmdSave" HorizontalAlignment="Left" Margin="48,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Save" Grid.Column="1" Click="cmdSave_Click">
<Image x:Name="imgSave" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\save_16xLG.png"/>
</Button>
<Button x:Name="cmdDelete" HorizontalAlignment="Left" Margin="139,36,0,0" VerticalAlignment="Top" Width="39" Height="40" Grid.Column="1" Click="cmdDelete_Click">
<Image x:Name="imgDelete" HorizontalAlignment="Left" Height="33" VerticalAlignment="Top" Width="32" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\action_Cancel_16xLG.png" ToolTip="Delete" RenderTransformOrigin="1.334,0.534"/>
</Button>
<Button x:Name="cmdNewStore" HorizontalAlignment="Left" Margin="179,36,0,0" VerticalAlignment="Top" Width="39" Height="40" Grid.Column="1" Click="cmdNewStore_Click">
<Image x:Name="imgNewStore" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\action_add_16xLG.png" ToolTip="Add New Store" RenderTransformOrigin="0.5,0.5"/>
</Button>
<Button x:Name="cmdExecute" HorizontalAlignment="Left" Margin="259,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Execute" Grid.Column="1" Click="cmdExecute_Click">
<Image x:Name="image" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="37" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\StatusAnnotations_Play_32xLG_color.png"/>
</Button>
<Button x:Name="cmdCancel" HorizontalAlignment="Left" Margin="299,36,0,0" VerticalAlignment="Top" Width="39" Height="40" ToolTip="Cancel" Grid.Column="1" Click="cmdCancel_Click">
<Image x:Name="imgCancel" HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="36" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\CancelApproval_32x32.png"/>
</Button>
<CheckBox x:Name="chOpenLastUsed" Content="Open Last Used File" Margin="360,48,0,0" VerticalAlignment="Top" Height="21" Width="147" HorizontalAlignment="Left" Grid.Column="1" Grid.ColumnSpan="2"/>
<ListView x:Name="lvStores" HorizontalAlignment="Left" Height="161" Margin="39,98,0,0" VerticalAlignment="Top" Width="370" Grid.ColumnSpan="2">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="ID" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Content="{Binding sID}" IsChecked="{Binding IsChecked}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" Width="Auto" DisplayMemberBinding="{Binding Path=sName}"/>
<GridViewColumn Header="Import File" Width="Auto" DisplayMemberBinding="{Binding Path=sImportFile}"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<Label x:Name="lblProgress" x:FieldModifier="public" Content="Status Text" HorizontalAlignment="Left" Margin="40,264,0,0" VerticalAlignment="Top" Grid.ColumnSpan="2" Width="369" BorderThickness="1" BorderBrush="#FF7C7C7C"/>
<Button x:Name="ComDialog" Grid.Column="1" HorizontalAlignment="Left" Margin="359,119,0,0" VerticalAlignment="Top" Width="48" Height="51" Grid.ColumnSpan="2">
<Image x:Name="imgComDialog" HorizontalAlignment="Left" Height="44" VerticalAlignment="Top" Width="48" Source="C:\Users\Niclas VMWare\Documents\Visual Studio 2015\Projects\CloneMacro\CloneMacro\images\DialogID_6220_32x.png"/>
</Button>
</Grid>
</Window>
.CS
public MainWindow()
{
// Leave this to show the UI
InitializeComponent();
lblProgress.Content = "";
lvStores.ItemsSource = ReadCSV(#"C:\Users\Niclas VMWare\Downloads\TEST FILE.pcf");
//SetButtonState();
string sFile;
}
public class Store
{
public string sName { get; set; }
public string sImportFile { get; set; }
public string sID { get; set; }
public bool IsChecked { get; set; }
public Store(string id, string strName, string isChecked, string strImportFile)
{
sName = strName.Replace("\"","");
sImportFile = strImportFile;
sID = id.Replace("\"","");
int iBool = Convert.ToInt32(isChecked);
switch (iBool)
{
case 0: IsChecked = false; break;
case 1: IsChecked = true; break;
default: throw new InvalidOperationException("Third value in PCF file must be 0 or 1!");
}
}
}
public IEnumerable<Store> ReadCSV(string fileName)
{
// Check file extension
string[] lines = File.ReadAllLines(Path.ChangeExtension(fileName, ".pcf"), Encoding.GetEncoding(65001));
// lines.Select allows to project each line as a Store.
// This will give IEnumerable<Store> back.
return lines.Select(line =>
{
string[] data = line.Split(',');
// Return store data with the data in order.
return new Store(data[0], data[1], data[2], fileName);
});
}

Modify your listview's first column definition to be
<GridViewColumn Header="ID" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Content="{Binding sID}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
I believe it will address your problem. Databinding may get affected and you'll need more XAML/code to handle that.
What I have done here is take the default definition of a GridViewColumn data template and replaced it with my own. You can read more about it in the Data templating topic.

Teach me wrong, but your csv file contains the columns ID, Name, IsChecked and you will parse it to new Store(id: data[0], strName: data[1], strImportFile: data[2]).
So following your example the properties of your new Store object will have the following values:
public class Store
{
public string sName { get; set; } // BØRSTER
public string sImportFile { get; set; } // 1
public string sID { get; set; } // 1662
public Store(string id, string strName, string strImportFile)
{
sName = strName;
sImportFile = strImportFile;
sID = id;
}
}
You should add another property to your class and another parameter to your constructor:
public bool IsChecked { get; set; }
public Store(string id, string strName, string isChecked, string strImportFile)
{
sID = id;
sName = strName;
IsChecked = isChecked == "1";
sImportFile = strImportFile;
}
So now you can create the new Store instance by calling
new Store(data[0], data[1], data[2], fileName).
The binding should now look like
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding sID}" />
At least let me give you a kind advice. You may take a look at the Microsoft Naming Guidelines.
For example: Properties should be named in PascalCasing and you also should avoid Hungarian notation like strName. But this is just my personal opinion.

Related

C# WPF Binding of group boxes and controls inside dependent on object

I have a list of objects in my mainViewmodel. When selecting in the listbox, depending on the selected type, a groupbox for this type should be visible and the properties should be binded.
I am not sure how i can achive this. I tried some stuff but i dont get it worked.
Foreach type of the ISimulator i have a groupbox and when I select it in the listbox, i try to show the right groupbox and bind the properties to that.
Thanks in advance
Xaml:
<Window x:Class="ControlCenter.Simulators.Gui.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="MainViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="1000">
<Grid x:Name="MainGrid" Margin="10,0,0,0" >
<Button Content="Add Simulator" HorizontalAlignment="Left" Margin="44,34,0,0" VerticalAlignment="Top" Width="88" />
<GroupBox x:Name="gb_Vehicle" Header="{Binding SimulatorId}" Margin="177,0,10,0" Visibility="Hidden">
<Grid Height="402" Margin="10,0,12,0">
<Label Content="StartCoordinates(x,y)" HorizontalAlignment="Left" Margin="21,21,0,0" VerticalAlignment="Top"/>
<Label x:Name="tb_Radius_Header" Content="Radius" HorizontalAlignment="Left" VerticalAlignment="Top" Width="126" Margin="21,91,0,0"/>
<Label x:Name="tb_Freq_Header" Content="Frequency" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="21,159,0,0"/>
<Label x:Name="tb_DeltaT_Header" Content="Delta T" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="21,213,0,0"/>
<Label x:Name="tb_Velocity_Header" Content="Velocity" HorizontalAlignment="Left" Margin="21,278,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="tb_Cord_X" HorizontalAlignment="Left" Margin="30,52,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="51" Text="{Binding SelectedItem.XCord, ElementName=lb_Vehicles,Mode=TwoWay ,ValidatesOnDataErrors=True , UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="tb_Cord_Y" HorizontalAlignment="Left" Margin="96,52,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="51" Text="{Binding SelectedItem.YCord, ElementName=lb_Vehicles,Mode=TwoWay ,ValidatesOnDataErrors=True , UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="tb_Radius" HorizontalAlignment="Left" Margin="30,122,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="52" Text="{Binding SelectedItem.Radius, ElementName=lb_Vehicles,Mode=TwoWay ,ValidatesOnDataErrors=True , UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="tb_DealtaT" HorizontalAlignment="Left" Margin="30,244,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding SelectedItem.DeltaT, ElementName=lb_Vehicles,Mode=TwoWay ,ValidatesOnDataErrors=True , UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="tb_Freq" HorizontalAlignment="Left" Margin="30,183,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding SelectedItem.Frequency, ElementName=lb_Vehicles,Mode=TwoWay ,ValidatesOnDataErrors=True , UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="tb_Velocity" HorizontalAlignment="Left" Margin="30,309,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding SelectedItem.Velocity, ElementName=lb_Vehicles, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/>
<WpfPlot Name="Plot" Margin="292,2,10,-2"/>
<Button x:Name="bt_Start" Content="Start" HorizontalAlignment="Left" Margin="21,366,0,0" VerticalAlignment="Top" Width="91" Height="26" />
<Button x:Name="bt_pos" Content="Draw" HorizontalAlignment="Left" Margin="134,366,0,0" VerticalAlignment="Top" Height="26" Width="77" />
</Grid>
</GroupBox>
<GroupBox x:Name="gb_Traffic" Header="{Binding SimulatorId}" Margin="177,0,10,0" Visibility="Hidden">
<Grid>
<ComboBox HorizontalAlignment="Left" Margin="27,57,0,0" VerticalAlignment="Top" Width="120"/>
<Label Content="Traffic Light Type" HorizontalAlignment="Left" Margin="27,10,0,0" VerticalAlignment="Top" Width="120"/>
<Label Content="Position (x,y)" HorizontalAlignment="Left" Margin="27,107,0,0" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="tb_Traffic_X" HorizontalAlignment="Left" Margin="27,162,0,0" TextWrapping="Wrap" Text="x" VerticalAlignment="Top" Width="60"/>
<TextBox x:Name="tb_Traffic_Y" HorizontalAlignment="Left" Margin="27,196,0,0" TextWrapping="Wrap" Text="y" VerticalAlignment="Top" Width="60"/>
<Label Content="PhasePlan" HorizontalAlignment="Left" Margin="220,55,0,0" VerticalAlignment="Top" Width="92"/>
<ListView d:ItemsSource="{d:SampleData ItemCount=5}" Margin="220,86,10,127">
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Left" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="OrderId" />
<GridViewColumn Header="Color"/>
<GridViewColumn Header="TotalDuration"/>
<GridViewColumn Header="BlinkDuration"/>
<GridViewColumn Header="Action"/>
</GridView>
</ListView.View>
</ListView>
<Button x:Name="bt_LoadConfig" Content="Load Config" HorizontalAlignment="Left" Margin="524,13,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.044,-0.116" Width="107"/>
<GroupBox Header="New Phase" Margin="10,313,189,20">
<Grid>
<Label Content="Color" HorizontalAlignment="Left" Margin="10,6,0,35" Height="30" Width="73"/>
<Label Content="Total Duration" HorizontalAlignment="Left" Margin="176,10,0,31" Height="30" Width="110"/>
<Label Content="Blink Duration" HorizontalAlignment="Left" Margin="341,7,0,34" Height="30" Width="110"/>
<ComboBox x:Name="cb_TrafficColor" HorizontalAlignment="Left" Margin="10,36,0,0" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="tb_TotalDuration" HorizontalAlignment="Left" Margin="176,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="tb_BlinkDuration" HorizontalAlignment="Left" Margin="341,39,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<Button x:Name="bt_AddPhase" Content="Add" HorizontalAlignment="Left" Margin="489,37,0,0" VerticalAlignment="Top" Width="62"/>
</Grid>
</GroupBox>
<Button x:Name="bt_SaveConfig" Content="Save Config" HorizontalAlignment="Left" Margin="651,13,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.044,-0.116" Width="107"/>
<Button x:Name="bt_StartTraffic" Content="Start" HorizontalAlignment="Left" Margin="669,397,0,0" VerticalAlignment="Top" Width="89"/>
</Grid>
</GroupBox>
<GroupBox x:Name="gb_AddSimulator" Header="Add Simulator" Margin="190,0,0,0" Visibility="Visible">
<Grid Margin="10,0,21,0">
<Label x:Name="tb_ObjectId_Header" Content="ObjectId" HorizontalAlignment="Left" Margin="241,29,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="tb_ObjectId" HorizontalAlignment="Left" Margin="222,66,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=SimulatorModel.Config.ObjectID, Mode=TwoWay ,ValidatesOnDataErrors=True , UpdateSourceTrigger=PropertyChanged}"/>
<Label x:Name="tb_IPAdress_Header" Content="IPAdress" HorizontalAlignment="Left" Margin="54,84,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="tb_IPAdress" HorizontalAlignment="Left" Margin="54,115,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=SimulatorModel.Config.IpAddress, Mode=TwoWay ,ValidatesOnDataErrors=True , UpdateSourceTrigger=PropertyChanged}"/>
<Label x:Name="tb_PortTCP_Header" Content="Port TCP" HorizontalAlignment="Left" Margin="236,84,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="tb_PortUDP" HorizontalAlignment="Left" Margin="55,169,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=SimulatorModel.Config.PortUDP, Mode=TwoWay ,ValidatesOnDataErrors=True , UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="tb_PortTCP" HorizontalAlignment="Left" Margin="222,115,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=SimulatorModel.Config.PortTCP, Mode=TwoWay ,ValidatesOnDataErrors=True , UpdateSourceTrigger=PropertyChanged}"/>
<Label x:Name="tb_PortGrpc_Header_" Content="Port GRPC" HorizontalAlignment="Left" Margin="236,138,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="tb_PortGrpc" HorizontalAlignment="Left" Margin="222,169,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=SimulatorModel.Config.PortGRPC, Mode=TwoWay ,ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"/>
<Label x:Name="tb_PortUDP_Header1" Content="Port UDP" HorizontalAlignment="Left" Margin="57,138,0,0" VerticalAlignment="Top"/>
<Button x:Name="bt_Add" Content="Add" HorizontalAlignment="Left" Margin="144,240,0,0" VerticalAlignment="Top" Width="119" Command="{Binding AddSimulatorCommand}" />
<ComboBox x:Name="cb_SimulatorType" HorizontalAlignment="Left" Margin="54,64,0,0" VerticalAlignment="Top" Width="120"/>
<Label x:Name="tb_PortGrpc_Header__Copy" Content="Simulator Type" HorizontalAlignment="Left" Margin="57,29,0,0" VerticalAlignment="Top"/>
</Grid>
</GroupBox>
<ListBox x:Name="lb_Simulators" d:ItemsSource="{Binding }" Margin="0,94,818,10"/>
</Grid>
</Window>
MainWindow.cs:
public partial class MainWindow : Window
{
private ILogger _logger;
public MainWindow()
{
InitializeComponent();
var mainViewModel = new MainViewModel(_logger);
this.DataContext = mainViewModel;
mainViewModel.SimulatorModels = new List<SimulatorModel>()
{
new SimulatorModel("1", null, null),
new SimulatorModel("2", null, null),
new SimulatorModel("3", null, null),
};
//lb_Simulators.ItemsSource = mainViewModel.SimulatorModels;
//lb_Simulators.DisplayMemberPath = "ID";
//gb_AddSimulator.DataContext = mainViewModel.SimulatorModel.Config;
//_logger.Information("Gui startet");
}
private void SetGroupBox(GroupBoxNames name, ISimulator simulator)
{
gb_Vehicle.Visibility = Visibility.Hidden;
gb_Traffic.Visibility = Visibility.Hidden;
gb_AddSimulator.Visibility = Visibility.Hidden;
switch (name)
{
case GroupBoxNames.AddSimulator:
gb_AddSimulator.Visibility = Visibility.Visible;
break;
case GroupBoxNames.Traffic:
gb_Traffic.Visibility = Visibility.Visible;
gb_Traffic.DataContext = simulator;
break;
case GroupBoxNames.Vehicle:
gb_Vehicle.Visibility = Visibility.Visible;
gb_Vehicle.DataContext = simulator;
break;
default:
break;
}
}
MainViewModel:
private ILogger _logger;
public IList<SimulatorModel> SimulatorModels { get; set; }
public SimulatorModel SimulatorModel { get; set; }
public ISimulator Simulator { get; set; }
public ICommand AddSimulatorCommand;
public ICommand RemoveSimulatorCommand;
public ICommand LoadSimulatorConfigCommand;
public ICommand SaveSimulatorConfigCommand;
public ICommand AddPhaseCommand;
public ICommand AddStartSimulatorCommand;
public bool CanStart { get; private set; } = true;
public event PropertyChangedEventHandler? PropertyChanged;
SimulatorModel:
public class SimulatorModel
{
public string ID { get; set; }
public SimulatorConfigModel Config { get; set; }
public ISimulator Simulator { get; set; }
public SimulatorModel(string id,SimulatorConfigModel configModel, ISimulator simulator)
{
ID = id;
Config = configModel;
Simulator = simulator;
}
}
Whenever you need dynamic data type based views you usually have to define a DataTemplate for each. Using the DataTemplate makes manual control of the GroupBox.Visibility obsolete and significantly reduces lines of code related to the related logic. See Microsoft Docs: Data Templating Overview
The following example shows how to display a dedicated GroupBox based on three imaginary ISimulator implementations: SimulatorA, SimulatorB and SimulatorC.
The associated GroupBox itself is hosted in a DataTemplate - one for each ISimulator implementation.
A ContentControl is used to render the DataTemplate. ContentControl.Comtent is bound to the SimulatorModel.Simulator property i.e. the ISimulator instance of the currently selected item of the ListBox:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type SimulatorA}">
<GroupBox x:Name="gb_Vehicle">
...
</GroupBox>
</DataTemplate>
<DataTemplate DataType="{x:Type SimulatorB}">
<GroupBox x:Name="gb_Traffic">
...
</GroupBox>
</DataTemplate>
<DataTemplate DataType="{x:Type SimulatorC}">
<GroupBox x:Name="gb_AddSimulator">
...
</GroupBox>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ListBox x:Name="SimulatorList"
ItemsSource="{Binding SimulatorModels}" />
<!-- Host for the GroupBox that is rendered via DataTemplate
based on the SimulatorModel.Simulator property.
Instead of binding directly to the ListBox.SelectedItem like below,
you can bind to a MainViewModel.SelectedSimulatorModel property, which is bound to the ListBox.SelectedItem -->
<ContenControl Content="{Binding ElementName=SimulatorList, Path=SelectedItem.Simulator}" />
</StackPanel>
</Window>
You should bind the ListBox, or XAML elements in general, rather than assigning values explicitly in code-behind. Especially in an MVVM scenario where you always focus on the data models rather than on the view's elements: you only update the data model and let the framework take care of the GUI via data binding. If you have to update the source collection dynamically, make the source collection e.g., SimulatorModels of type ObservableCollectio<T>.

WPF - Change Controls based on listviewitem selection. Controls not updating

I'm trying to update the controls present on my Main Window based on the listviewitem selected by the user, but when the listviewitem selection is changed the controls do not update.
I used this post as reference How to dynamically change a WPF control's template using a checkbox?
EDIT: I initially used ContentTemplate but changed this to DataTemplate based on suggestions, however it still is not updating
The XMAL for my Main Window is
<Window.Resources>
<DataTemplate x:Key="Default">
<Grid Margin="20,280,0,0" />
</DataTemplate>
<DataTemplate x:Key="ERAFileSelect">
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="218" Margin="20,280,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
<Grid Name="grdFileSelect">
<Label x:Name="lblProcessContent" Content="Drag File or Manually Select File" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
<TextBox x:Name="txtEraFileName" HorizontalAlignment="Left" Height="23" Margin="10,80,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="235"/>
<Button x:Name="btnSelectFiles" Content="Manually Select File(s)" HorizontalAlignment="Left" Margin="10,161,0,0" VerticalAlignment="Top" Width="235" Height="45"/>
</Grid>
</Border>
</DataTemplate>
<DataTemplate x:Key="FCSFileSelect">
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="218" Margin="20,280,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
<Grid Name="grdFileSelect">
<Label x:Name="lblProcessContent" Content="Drag File or Manually Select Files" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
<TextBox x:Name="txtFCSFileName_TQ02" HorizontalAlignment="Left" Height="23" Margin="10,40,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
<Button x:Name="btnSelectFiles_TQ02" Content="Select" HorizontalAlignment="Left" Margin="189,37,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
<TextBox x:Name="txtFCSFileName_TQ11" HorizontalAlignment="Left" Height="23" Margin="10,105,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
<Button x:Name="btnSelectFiles_TQ11" Content="Selec" HorizontalAlignment="Left" Margin="189,100,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
<TextBox x:Name="txtFCSFileName_TQ16" HorizontalAlignment="Left" Height="23" Margin="10,170,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="174"/>
<Button x:Name="btnSelectFiles_TQ16" Content="Select" HorizontalAlignment="Left" Margin="189,165,0,0" VerticalAlignment="Top" Width="56" Height="28"/>
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
<Grid Margin="0,0,2,0">
<GroupBox x:Name="gbxProgress" Header="Progress" HorizontalAlignment="Left" Margin="298,105,0,0" VerticalAlignment="Top" Height="445" Width="462" Foreground="Black">
<ListBox x:Name="lbxProgress" HorizontalAlignment="Left" Height="408" Margin="10,10,0,0" VerticalAlignment="Top" Width="431" Foreground="Black" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Progress.Message}" />
</GroupBox>
<Button x:Name="btnStart" Content="Start" HorizontalAlignment="Left" Margin="20,513,0,0" VerticalAlignment="Top" Width="100" Height="37" IsEnabled="{Binding Properties.StartButtonEnabled}" Click="btnStart_Click"/>
<Button x:Name="btnCancel" Content="Cancel" HorizontalAlignment="Left" Margin="177,513,0,0" VerticalAlignment="Top" Width="100" Height="37"/>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="70" Margin="20,21,0,0" VerticalAlignment="Top" Width="740" CornerRadius="15">
<Grid>
<Image HorizontalAlignment ="Left" Margin="10" Height="50" Width="50" VerticalAlignment="Center" Source="/Lib/Icons/User.png" />
<TextBlock Name="txtUser" FontSize="20" Height="30" Width="200" Foreground="Red" HorizontalAlignment="Left" Margin="78,19,0,19"/>
<Image HorizontalAlignment ="Left" Margin="443,8,0,10" Height="50" Width="50" VerticalAlignment="Center" Source="Lib/Icons/Watch.png" />
<TextBlock x:Name="txtRunTime" FontSize="20" Height="30" Width="200" Foreground="Red" HorizontalAlignment="Left" Margin="519,19,0,19" Text="{Binding AppRunTime.TimeElapsed}" />
</Grid>
</Border>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="144" Margin="20,119,0,0" VerticalAlignment="Top" Width="257" CornerRadius="15">
<Grid>
<Label x:Name="lblProcessSelection" Content="Process Selection" HorizontalAlignment="Center" VerticalAlignment="Top" Width="257" HorizontalContentAlignment="Center"/>
<ListView x:Name="lvProcessSelection" HorizontalAlignment="Left" Height="93" Margin="10,30,0,0" VerticalAlignment="Top" Width="235" BorderThickness="0" SelectionChanged="lvProcessSelection_SelectionChanged">
<ListViewItem Name="itmERA" Content="Expense Reserve Automation"/>
<ListViewItem Name="itmFCS" Content="Financial Close Status"/>
<ListViewItem Name="itmPEL" Content="Peel"/>
</ListView>
</Grid>
</Border>
<ContentControl DataContext="{Binding Properties}" Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{StaticResource ERAFileSelect}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedProcess}" Value="Expense Reserve Automation">
<Setter Property="ContentTemplate" Value="{StaticResource ERAFileSelect}" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedProcess}" Value="Financial Close Status">
<Setter Property="ContentTemplate" Value="{StaticResource FCSFileSelect}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
ViewModel Code is
public class MainWindowModel
{
public ApplicationRunTime AppRunTime { get; set; }
public LogMessage Progress { get; set; }
public MainWindowProperties Properties { get; set; }
public MainWindowModel()
{
AppRunTime = new ApplicationRunTime();
Progress = new LogMessage();
Properties = new MainWindowProperties();
Properties.StartButtonEnabled = false;
}
}
With the MainWindowProperties class
public class MainWindowProperties
{
public bool StartButtonEnabled { get; set; }
public string SelectedProcess { get; set; }
}
And within my MainWindow Constructor I have set the DataContext
mainWindowModel = new MainWindowModel();
this.DataContext = mainWindowModel;
When the selection from lvProcessSelection is changed the following code is executed
if (lvProcessSelection.SelectedItems.Count > 0)
{
mainWindowModel.Properties.SelectedProcess = ((ListViewItem)lvProcessSelection.SelectedItem).Content.ToString();
}
else
{
mainWindowModel.Properties.SelectedProcess = string.Empty;
}
This will update SelectedProcess within my ViewModel with either "Expense Reserve Automation" or "Financial Close Status"
I know the DataContext is set correctly for my ViewModel (but may not be for the ContentControl) as I am able to update lbxProgress with new messages and update txtRunTime with the application RunTime
However when I change the selection on lvProcessSelection nothing happens; the default controls of ERAFileSelect remains.
Could anybody point me in the right direction on how to solve this?
Could anybody point me in the right direction on how to solve this?
Your MainWindowProperties class should implement the INotifyPropertyChanged interface and raise change notifications whenever the SelectedProcess property is set to a new value:
public class MainWindowProperties : INotifyPropertyChanged
{
public bool StartButtonEnabled { get; set; }
private string _selectedProcess;
public string SelectedProcess
{
get { return _selectedProcess; }
set { _selectedProcess = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Please refer to MSDN for more information about this common interface: https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx
Every view model/model that you bind to must implement this interface and raise change notifications for any target value in the view to be updated.
Why you are not using Data template? Data template will work in this scenario.

ListBox SelectionChanged only once?

I have a ListBox which I add items to. Each time i select an item which is an object of a Person this person properties should be showed in textboxes. This person have person properties like age, name, sex and so on.
my listbox selection changed event only triggers one time or on new added items. It doesn't trigger when i click and an that is not just added.
Mainwindow.xaml.cs
namespace GUI_WPF_Eksamen
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Backlog bl = new Backlog();
public MainWindow()
{
InitializeComponent();
DataContext = bl;
this.PriorityComboBox.Items.Add("High");
this.PriorityComboBox.Items.Add("Medium");
this.PriorityComboBox.Items.Add("Low");
}
private void AddToProductBackLogBtn_Click(object sender, RoutedEventArgs e)
{
this.ProductBacklogList.Items.Add(bl);
this.NameTextBox.Text = String.Empty;
}
private void ProductBacklogList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = this.ProductBacklogList.SelectedItem as Backlog;
this.NameLabel.Content = item.NAME;
this.DescriptionTextBlock.Text = item.DESCRIPTION;
this.PriorityLabel.Content = item.PRIORITY;
this.TimeLabel.Content = item.TIME;
}
private void AddToSprint_Click(object sender, RoutedEventArgs e)
{
var currentItem = this.ProductBacklogList.SelectedItem as Backlog;
this.SprintBacklogList.Items.Add(currentItem);
}
}
}
Mainwindow.xaml
<Window x:Class="GUI_WPF_Eksamen.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GUI_WPF_Eksamen"
Title="GUI WPF application" Height="800" Width="1200">
<Window.Background>
<ImageBrush ImageSource="Images/chalkboard.jpg"/>
</Window.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="69*"/>
<RowDefinition Height="700*"/>
</Grid.RowDefinitions>
<Label x:Name="Title" Content="SCRUM-BOARD XXL" HorizontalAlignment="Center" HorizontalContentAlignment="Center" Margin="15,10,5,0" VerticalAlignment="Top" Width="1172" Height="56" FontSize="36" FontStyle="Italic" FontWeight="Bold" Foreground="White"/>
<Grid HorizontalAlignment="Left" Height="680" Margin="15,10,0,0" Grid.Row="1" VerticalAlignment="Top" Width="354">
<Grid.RowDefinitions>
<RowDefinition Height="94*"/>
<RowDefinition Height="44*"/>
<RowDefinition Height="131*"/>
<RowDefinition Height="53*"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="46*"/>
<RowDefinition Height="272*"/>
</Grid.RowDefinitions>
<Label Content="Navn" HorizontalAlignment="Left" Margin="0,44,0,0" VerticalAlignment="Top" Width="77" FontSize="16" Foreground="White"/>
<Label Content="Beskrivelse
" HorizontalAlignment="Left" Margin="0,10,0,0" VerticalAlignment="Top" Foreground="White" FontSize="16" Height="31" Grid.Row="1"/>
<Label Content="Prioritet" HorizontalAlignment="Left" Margin="0,7,0,0" VerticalAlignment="Top" Width="67" FontSize="16" Foreground="White" Grid.Row="3"/>
<Label Content="Estimeret tidsforbrug" HorizontalAlignment="Left" Margin="0,10,0,0" VerticalAlignment="Top" Foreground="White" FontSize="16" Grid.Row="4" Grid.RowSpan="2"/>
<TextBox x:Name="NameTextBox" HorizontalAlignment="Left" Height="23" Margin="51,52,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="303" Opacity="0.5" Text="{Binding Path=NAME}"/>
<ComboBox x:Name="PriorityComboBox" HorizontalAlignment="Left" Margin="73,12,0,0" VerticalAlignment="Top" Width="152" RenderTransformOrigin="0.5,0.5" Opacity="0.5" Grid.Row="3" SelectedItem="{Binding Path=PRIORITY}">
<ComboBox.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="0.036"/>
<TranslateTransform/>
</TransformGroup>
</ComboBox.RenderTransform>
</ComboBox>
<TextBox x:Name="TimeTextBox" HorizontalAlignment="Left" Height="23" Margin="0,6,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="204" Opacity="0.5" Grid.Row="5" Text="{Binding Path=TIME}"/>
<Label Content="time(r)" HorizontalAlignment="Left" Margin="209,38,0,0" VerticalAlignment="Top" Foreground="White" FontSize="16" Width="57" Grid.Row="4" Grid.RowSpan="2"/>
<TextBox x:Name="DescriptionTextBox" HorizontalAlignment="Left" Height="111" Margin="0,10,0,0" Grid.Row="2" TextWrapping="Wrap" VerticalAlignment="Top" Width="354" Opacity="0.5" Text="{Binding Path=DESCRIPTION}"/>
<Button x:Name="AddToProductBackLogBtn" Content="Add Backlog item" HorizontalAlignment="Left" Grid.Row="6" VerticalAlignment="Top" Width="200" Height="27" Margin="66,0,0,0" Background="White" Opacity="0.7" Click="AddToProductBackLogBtn_Click"/>
</Grid>
<Grid HorizontalAlignment="Left" Height="680" Margin="374,10,0,0" Grid.Row="1" VerticalAlignment="Top" Width="808" RenderTransformOrigin="0.459,0.431">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="79*"/>
<ColumnDefinition Width="47*"/>
<ColumnDefinition Width="76*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="209*"/>
<RowDefinition Height="131*"/>
</Grid.RowDefinitions>
<Label Content="Navn" HorizontalAlignment="Left" Margin="10,10,0,0" Grid.Row="1" VerticalAlignment="Top" FontSize="16" Foreground="White" Height="31" Width="47"/>
<Label Content="Beskrivelse" HorizontalAlignment="Left" Margin="10,55,0,0" Grid.Row="1" VerticalAlignment="Top" Foreground="White" FontSize="16" Height="31" Width="87"/>
<Label Content="Prioritet
" HorizontalAlignment="Left" Margin="10,10,0,0" Grid.Row="1" VerticalAlignment="Top" Foreground="White" FontSize="16" Height="32" Grid.Column="1" Width="66"/>
<Label Content="Estimeret tidsforbrug" Grid.Column="1" HorizontalAlignment="Left" Margin="10,55,0,0" Grid.Row="1" VerticalAlignment="Top" Foreground="White" FontSize="16" Height="31" Width="159"/>
<Label x:Name="PriorityLabel" Content="" Grid.Column="1" HorizontalAlignment="Left" Margin="90,10,0,0" Grid.Row="1" VerticalAlignment="Top" FontSize="16" Foreground="White" Width="79" Height="31"/>
<Label x:Name="TimeLabel" Grid.Column="2" HorizontalAlignment="Left" Margin="10,55,0,0" Grid.Row="1" VerticalAlignment="Top" Foreground="White" FontSize="16" Width="208" Height="31"/>
<ListBox x:Name="ProductBacklogList" HorizontalAlignment="Left" Height="353" Margin="10,55,0,0" VerticalAlignment="Top" Width="292" DisplayMemberPath="NAME" Opacity="0.505" SelectionChanged="ProductBacklogList_SelectionChanged" RenderTransformOrigin="0.5,0.5">
<ListBox.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleY="-0.195"/>
<RotateTransform/>
<TranslateTransform Y="-0.497"/>
</TransformGroup>
</ListBox.RenderTransform>
</ListBox>
<ListBox x:Name="SprintBacklogList" HorizontalAlignment="Left" Height="353" Margin="10,55,0,0" VerticalAlignment="Top" Width="284" DisplayMemberPath="NAME" Grid.Column="2" Opacity="0.5"/>
<Label x:Name="NameLabel" HorizontalAlignment="Left" Margin="62,14,0,0" Grid.Row="1" VerticalAlignment="Top" Width="244" Height="27" Content="{Binding Path=NAME}" Foreground="White"/>
<Button x:Name="AddToSprint" Content="Add >>" Grid.Column="1" HorizontalAlignment="Left" Margin="54,201,0,0" VerticalAlignment="Top" Width="75" Height="20" Opacity="0.7" Click="AddToSprint_Click"/>
<TextBlock x:Name="DescriptionTextBlock" HorizontalAlignment="Left" Margin="10,86,0,0" Grid.Row="1" TextWrapping="Wrap" VerticalAlignment="Top" Height="166" Width="296" Foreground="White"/>
</Grid>
</Grid>
That way of selection changed can be accomplished easily:
Have a look here:
<Window x:Class="ListBoxSelection.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<ListBox ItemsSource="{Binding persons}" IsSynchronizedWithCurrentItem="True" DockPanel.Dock="Top">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="5,0"/>
<TextBlock Text="{Binding Age, StringFormat=is {0} years old}" Margin="5,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Orientation="Horizontal" DataContext="{Binding persons}" DockPanel.Dock="Top">
<TextBlock Text="You have selected: " FontWeight="SemiBold"/>
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
Margin="5,0"
FontWeight="SemiBold"
VerticalAlignment="Top"
HorizontalAlignment="Center"/>
<TextBox Text="{Binding Age, UpdateSourceTrigger=PropertyChanged}"
Margin="5,0"
FontWeight="SemiBold"
VerticalAlignment="Top"
HorizontalAlignment="Left"/>
</StackPanel>
<Button Content="Add Item" DockPanel.Dock="Top" Width="60" VerticalAlignment="Top" Margin="20" Click="btnAddItem_Click"/>
</DockPanel>
Note this down: IsSynchronizedWithCurrentItem="True"
From MSDN:
Gets or sets a value that indicates whether a Selector should keep the
SelectedItem synchronized with the current item in the Items property.
What's the next step? Display the selected item:
<StackPanel DataContext="{Binding persons}"/>
StackPanel is not an ItemsControl, it will not try to display all the items in persons but instead it will look for the selected one.
The ICollectionView interface contains a member called CurrentItem. What the IsSynchronizedWithCurrentItem does is: whenever an item is clicked on the ItemsControl, it sets the CurrentItem for the collection view. The ICollectionView also has two events: CurrentItemChanging and CurrentItemChanged. When the IsSynchronizedWithCurrentItem property is set, the ItemsControl will update the SelectedItem based on what the ICollectionView's CurrentItem is.
Further more, using UpdateSourceTrigger=PropertyChanged you will be able to update you selected item and this will be immediately displayed in the ListBox.
OK, that's about, here is the rest of the code:
public class Person : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
private int _Age;
public int Age
{
get { return _Age; }
set
{
_Age = value;
PropertyChanged(this, new PropertyChangedEventArgs("Age"));
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
And the codebehind:
public partial class MainWindow : Window
{
public ObservableCollection<Person> persons { get; set; }
public Person SelectedPerson
{
get { return (Person)GetValue(SelectedPersonProperty); }
set { SetValue(SelectedPersonProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectedPerson. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedPersonProperty =
DependencyProperty.Register("SelectedPerson", typeof(Person), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
InitializeComponent();
persons = new ObservableCollection<Person>();
persons.Add(new Person() { Name = "Name1", Age = 20 });
persons.Add(new Person() { Name = "Name2", Age = 25 });
persons.Add(new Person() { Name = "Name3", Age = 30 });
this.DataContext = this;
}
private void btnAddItem_Click(object sender, RoutedEventArgs e)
{
persons.Add(new Person() { Name = "NameAdded", Age = 50 });
}
}
As you see, your SelectionChanged handler is not needed anymore.
You may be asking, what is that SelectedPerson in the code behind:
Add this binding on the ListBox:
SelectedItem="{Binding SelectedPerson}"
And in that AddToSprint_Click use the SelectedPerson to get the Person instead of directly accessing the ListBox.

Datagrid not showing data in wpf with c#

I am trying to use a dataGrid in WPF with c#. But I cannot get my datagrid to show any of my data in the table when I run my program in debug mode. I have this code executing when the datagrid loads. But all I see is an empty square.
private void dataGrid1_Loaded(object sender, RoutedEventArgs e)
{
var items = new List<SaveTable>();
items.Add(new SaveTable("A" , 0));
items.Add(new SaveTable("B" , 0));
items.Add(new SaveTable("C" , 0));
items.Add(new SaveTable("D" , 0));
items.Add(new SaveTable("E" , 0));
var grid = sender as DataGrid;
grid.ItemsSource = items;
}
I save a class named SaveTable which looks like this:
class SaveTable
{
public string Name { get; set; }
public double Value { get; set; }
public SaveTable(string name, double value)
{
this.Name = name;
this.Value = value;
}
}
I got this code format online and it seems like everything is right? any suggestions?
here is the xaml code for that window
<Window x:Class="RobustCalculator.Storage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Storage" Height="499" Width="546" Activated="Window_Activated" Loaded="Window_Loaded">
<Grid>
<TextBlock Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="textBlock1" Text="A" VerticalAlignment="Top" />
<TextBox HorizontalAlignment="Left" Margin="24,10,0,306" Name="valueA" Width="120" TextChanged="valueA_TextChanged" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="24,39,0,0" Name="valueB" VerticalAlignment="Top" Width="120" TextChanged="valueB_TextChanged" />
<TextBlock Height="20" HorizontalAlignment="Left" Margin="10,42,0,0" Name="textBlock2" Text="B" VerticalAlignment="Top" Width="20" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="24,71,0,0" Name="valueC" VerticalAlignment="Top" Width="120" TextChanged="valueC_TextChanged" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="10,72,0,0" Name="textBlock3" Text="C" VerticalAlignment="Top" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="10,101,0,0" Name="textBlock4" Text="D" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="24,98,0,0" Name="valueD" VerticalAlignment="Top" Width="120" TextChanged="valueD_TextChanged" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="24,130,0,0" Name="valueE" VerticalAlignment="Top" Width="120" TextChanged="valueE_TextChanged" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="11,131,0,0" Name="textBlock5" Text="E" VerticalAlignment="Top" />
<DataGrid AutoGenerateColumns="False" Height="200" HorizontalAlignment="Left" Margin="235,130,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="200" SelectionChanged="dataGrid1_SelectionChanged" Loaded="dataGrid1_Loaded" />
</Grid>
I added a breakpoint and the code isn't being executed. I am using the Loaded event, should I be using a different event?
Your code works fine with Loaded event but at the moment you set AutoGenerateColumns="False" and don't define columns. You need to either define columns manually
<DataGrid AutoGenerateColumns="False" ... Loaded="dataGrid1_Loaded">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
<DataGridTextColumn Binding="{Binding Value}" Header="Value"/>
</DataGrid.Columns>
</DataGrid>
or let it auto generate columns
<DataGrid AutoGenerateColumns="True" ... Loaded="dataGrid1_Loaded"/>

I am trying to figure out whats wrong with my list

The only way I can describe whats happening is with an image so I hope this shows up, I think my problem is within the itemsource because I put these in a listbox and there is no blank spaces in the email list, in col1 it shows the names, and in col2 it shows the emails, but there not on the same rows, everything is pushed down.
here is the xaml
<Window x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="492" Width="865" ResizeMode="CanMinimize">
<Grid>
<Label Content="Name" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" IsEnabled="False" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="12,46,0,0" Name="textBox1" VerticalAlignment="Top" Width="180" />
<Label Content="Email" Height="28" HorizontalAlignment="Left" Margin="12,138,0,0" Name="label3" VerticalAlignment="Top" IsEnabled="False" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="12,172,0,0" Name="textBox3" VerticalAlignment="Top" Width="180" />
<Label Content="Website" Height="28" HorizontalAlignment="Left" Margin="12,75,0,0" Name="label4" VerticalAlignment="Top" IsEnabled="False" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="12,109,0,0" Name="textBox4" VerticalAlignment="Top" Width="180" />
<Calendar Height="170" HorizontalAlignment="Left" Margin="12,235,0,0" Name="calendar1" VerticalAlignment="Top" Width="180" />
<Label Content="Send Date" Height="28" HorizontalAlignment="Left" Margin="12,203,0,0" Name="label2" VerticalAlignment="Top" IsEnabled="False" />
<TabControl Height="391" HorizontalAlignment="Left" Margin="225,14,0,0" Name="tabControl1" VerticalAlignment="Top" Width="606">
<TabItem Header="My" Name="tabItem1" IsEnabled="True">
<Grid>
<ListView Height="359" ItemsSource="{Binding Tab1Collection}" HorizontalAlignment="Left" Name="listView1" VerticalAlignment="Top" Width="596">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding name1}" Header="Name" Width="150" />
<GridViewColumn DisplayMemberBinding="{Binding email1}" Header="Email" Width="255" />
<GridViewColumn DisplayMemberBinding="{Binding website1}" Header="Website" Width="200" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</TabItem>
<TabItem Header="Finished" Name="tabItem2" IsEnabled="true">
<Grid>
<ListView Height="359" HorizontalAlignment="Left" Name="listView2" VerticalAlignment="Top" Width="596">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="150" />
<GridViewColumn Header="Email" Width="150" />
<GridViewColumn Header="Website" Width="150" />
<GridViewColumn Header="Delivered On" Width="150" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</TabItem>
<TabItem Header="Results" Name="tabItem3" IsEnabled="False">
<Grid />
</TabItem>
<TabItem Header="Directory" Name="tabItem4" IsEnabled="true" IsSelected="True">
<Grid Height="362"></Grid>
</TabItem>
</TabControl>
<Button Content="Add Contact" Height="29" HorizontalAlignment="Left" Margin="97,411,0,0" Name="button1" VerticalAlignment="Top" Width="95" />
</Grid>
here is the code
private List<string> names = new List<string>();
private List<string> Emails = new List<string>();
public MainWindow()
{
InitializeComponent();
names.Add("test123");
names.Add("test123");
names.Add("test123");
names.Add("tst123");
names.Add("test123");
names.Add("tst123");
Emails.Add("test123#Gmail.com");
Emails.Add("test123#Gmail.com");
Emails.Add("test123#Gmail.com");
Emails.Add("test123#Gmail.com");
Emails.Add("test123#Gmail.com");
Emails.Add("test123#Gmail.com");
foreach(var n in names) {
listView1.Items.Add(new {name1 = n});
}
foreach(var e in Emails) {
listView1.Items.Add(new {email1 = e});
}
}
here is the image to explain whats happening, everything should be on the same row.
You are adding 2 different collections to the listView by iterating through each of them separately so it's obvious that you'll get the effect you are seeing.
You need to create a class with 2 properties, name and email and then bind the ListView to this class. Something like:
public class Person
{
public Person(string name,string email)
{
Name=name;
Email=email;
}
public string Name {get;set;}
public string Email {get;set;}
}
List<Person> people = {new Person("name1","test1#gmail.com"
,new Person("name2","test2#gmail.com"
,new Person("name3","test3#gmail.com"
,new Person("name4","test4#gmail.com")};
Now you can simply bind the listview as so:
listView1.ItemsSource=people;
You're managing two different List, and you're not merging them, you're inserting one list, and then another one.
Considering two List have the same number of Items, you can do something Like
for(int index = 0; index < names.Count;index++)
{
listView1.Items.Add(new {email1 = Emails[index], name1 = names[index] });
}
I don't remember the List syntax and properties, so if this doesn't work (or are better options) please edit me

Categories