DataGrid binding collection with nested Properties - wpf

I have a Person and Address class. The Person class has properties like Name, Gender etc and Address. The Address class has properties like Street, City as strings. If I have a collection of Person called "people" which is a List(Of Person). And I bind "people" to a DataGrid in WPF. The Name column is fine, but the "City" column is always empty.
Class Address
Sub New()
End Sub
Private _city As String
Property City() As String
Get
Return _city
End Get
Set(ByVal value As String)
_city = vaule
End Set
End Property
End Class
Class Person
Sub New()
End Sub
Private _name As String = ""
Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = vaule
End Set
End Property
Private _address As Address
Property Address() As Address
Get
Return _address
End Get
Set(ByVal value As Address)
_address = vaule
End Set
End Property
End Class
Under the Window_Loaded event, I have
Dim people As List(of Person) = _DAL.GetAllPeople()
Me.myDataGrid.ItemsSource = people
Dim nameBinding As Binding = New Binding
nameBinding.Path = New PropertyPath("Name")
Me.nameColumn.Binding = nameBinding 'This works fine in datagrid
Dim addressBinding As Binding = New Binding
addressBinding.Path = New PropertyPath("Address.City")
Me.cityColumn.Binding = addressBinding 'This does not work
XAML CODE:
<DataGrid x:Name="myDataGrid" HorizontalAlignment="Left" Margin="8,177.4,0,38" Width="240" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="nameColumn" CanUserResize="False" IsReadOnly="True" Header="Name" Width="100"/>
<DataGridTextColumn x:Name="cityColumn" CanUserResize="False" Header="City" IsReadOnly="True" Width="*" />
</DataGrid.Columns>
</DataGrid>

Related

Access to TextBoxes in all ListView rows - WPF - VB.NET

How can I access to TextBoxes in all ListView rows? I have also tried the two-way method, but it is only one-way.
<ListView Name="ListViewParameters" >
<ListView.View>
<GridView>
<GridViewColumn Header="Value" Width="120" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox x:Name="TextWidth" Text="{Binding Path=Width, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
...
.
Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
ListViewParameters.ItemsSource = Parameters
End Sub
.
Public Structure Parameter
Private _width As Integer
Private _length As Integer
Private _height As Integer
Property Width() As Integer
Get
Return _width
End Get
Set(Value As Integer)
_width = Value
End Set
End Property
Property Length() As Integer
Get
Return _length
End Get
Set(Value As Integer)
_length = Value
End Set
End Property
Property Height() As Integer
Get
Return _height
End Get
Set(Value As Integer)
_height = Value
End Set
End Property
End Structure
Public ReadOnly Parameters As New ObservableCollection(Of Parameter)
My goal is to calculate the volume:
Private Sub ButtonCalculate_Click(sender As Object, e As RoutedEventArgs)
Dim volume As Integer = 1
For Each t As TextBox In ListParameters
volume *= CInt(t.Text)
Next
MsgBox(volume.ToString)
End Sub
(This is for learning only)

WPF VB.Net Datagrid Value from a specific Cell in FullRow Selection Mode?

How can I get a Value from a specific Cell in a Datagrid with the Selection Mode FullRow ?
At the moment I use this command, but it only display's the Value if I manually select the cell:
Public Sub MenuItem_Click(sender As Object, e As RoutedEventArgs)
Dim selectedData As String = ""
Dim wert As String = ""
For Each dataGridCellInfo In myGridView.SelectedCells()
Dim pi As Reflection.PropertyInfo = dataGridCellInfo.Item.[GetType]().GetProperty(dataGridCellInfo.Column.Header.ToString())
Dim value = pi.GetValue(dataGridCellInfo.Item, Nothing)
selectedData += dataGridCellInfo.Column.Header + ": " + value.ToString() + vbLf
wert = value.ToString
Next
MessageBox.Show(selectedData)
End Sub
But I don't want to manually select the cell all time.
I just want to click on any cell in that Row and get always the value from the cell "Pfad" and put it in a String.
XAML DataGrid Code:
<DataGrid Name="myGridView" SelectionUnit="Cell" IsReadOnly="True" ItemsSource="{Binding}" Grid.ColumnSpan="3" Background="#FFA4A4A4" BorderThickness="2" BorderBrush="#FF6A6F77" AutoGenerateColumns="False" Margin="10,31,10,149.714" GridLinesVisibility="None">
<DataGrid.Columns>
<DataGridTextColumn Header="Track" Binding="{Binding Path=Track}" Width="100"/>
<DataGridTemplateColumn Header="">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Width="50" Height="50" VerticalAlignment="Center" HorizontalAlignment="Center" Source="{Binding Path=Image}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Path=Endung}" Width="100" Header=" Container"/>
<DataGridTextColumn Binding="{Binding Path=Album}" Width="100" Header="Album"/>
<DataGridTextColumn Binding="{Binding Path=Bitrate}" Width="100" Header="Bitrate"/>
<DataGridTextColumn Binding="{Binding Path=Pfad}" Width="100" Header="Pfad"/>
</DataGrid.Columns>
</DataGrid>
Code-Behind:
Public Structure Austauscher
Dim files As New ObservableCollection(Of Austauscher)
Private _track As String
Private _image As BitmapImage
Private _album As String
Private _pfad As String
Private _bitrate As String
Private _endung As String
Property Track() As String
Get
Return _track
End Get
Set(ByVal Value As String)
_track = Value
End Set
End Property
Property Image As BitmapImage
Get
Return _image
End Get
Set(ByVal Value As BitmapImage)
_image = Value
End Set
End Property
Property Album() As String
Get
Return _album
End Get
Set(ByVal Value As String)
_album = Value
End Set
End Property
Public Property Pfad As String
Get
Return _pfad
End Get
Set(ByVal Value As String)
_pfad = Value
End Set
End Property
Property Bitrate As String
Get
Return _bitrate
End Get
Set(ByVal Value As String)
_bitrate = Value
End Set
End Property
Property Endung As String
Get
Return _endung
End Get
Set(ByVal Value As String)
_endung = Value
End Set
End Property
End Structure
At first you need tu open de event "CellClick" on your datagridview and put de following code:
If (e.ColumnIndex <> -1) And (e.RowIndex <> -1) Then
Dim selectedCell as string = ""
selectedCell = myGridView.rows(e.rowIndex).cells("numberOfCell").valeu
End If
If this Answer has help you. Pleas mark this at the correct Answer.

DAL Generator: How to get Grid Checkbox?

I am building a WPF D.A.L. generator.
In my main page, I have a DataGrid populated with a list of the tables in my database.
I also have an extra checkbox column called ShouldInclude? I intend to use this to determine whether or not the table should be included in the generation... yes if checked, no if un-checked.
Because I am populating the DataGrid's ItemSource with a strongly typed list of some basic info TableName, Schema, Columns, I am now finding myself at a loss as to how I can get the checked value of the checkbox so I can make that determination on whether to include it or not.
Here are my functions that build out my table typing class code files:
Private Sub GenerateTyping(ByVal _DG As DataGrid)
For Each i As TableTyping In _DG.Items
'check if should be generated
Dim _TString As String = String.Empty
Using _sr As New StreamReader(Common.GetPath() & "Class Templates\CSharp\Typing\XXX_Typing.txt")
_TString = _sr.ReadToEnd()
_sr.Close()
End Using
Dim _FN As String = i.Name & "_Typing.cs"
Dim _Props As New StringBuilder()
Dim _CL As List(Of ColumnTyping) = i.Columns
For Each col In _CL
With _Props
Dim _PropStr As String = "public " & Common.GetClrType(col.Type) & " " & col.Name & " { get; set; }"
.AppendLine(" " & _PropStr)
End With
Next
'Write the new class files
_TString = _TString.Replace("##TABLENAME##", If(i.Schema.Length > 0, i.Schema & "_", "") & i.Name).Replace("##THE_PROPERTIES##", _Props.ToString())
If Not Directory.Exists(FilePath & "\Typing\") Then
Directory.CreateDirectory(FilePath & "\Typing\")
End If
Using _sw As New StreamWriter(FilePath & "\Typing\" & If(i.Schema.Length > 0, i.Schema & "_", "") & i.Name & "_Typing.cs", False)
_sw.Write(_TString)
_sw.Close()
End Using
_TString = String.Empty
_Props.Clear()
Next
End Sub
Partial Public Class TableTyping
Public Property ID As Integer
Public Property Name As String
Public Property Schema As String
Public Property Columns As List(Of ColumnTyping)
End Class
Partial Public Class ColumnTyping
Public Property ID As Integer
Public Property Name As String
Public Property Type As SqlDataType
Public Property Length As Integer
Public Property DefaultValue As String
Public Property Precision As Integer
Public Property Scale As Integer
End Class
My datagrid simply consists of 3 columns. Include?, Table Schema, Table Name, which is populated via:
<DataGrid EnableRowVirtualization="True" Name="dgTables" IsReadOnly="True" AutoGenerateColumns="False" FontFamily="Calibri" FontSize="14" IsEnabled="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Include?">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding ID}" HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="True" Name="ckTblInclude" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Schema}" Header="Schema"/>
<DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
</DataGrid.Columns>
</DataGrid>
AND:
_tg.ItemsSource = _Table
Private Sub GrabTables()
Dim _Db As Database = Srv.Databases(DBName)
Dim _Tbls As TableCollection = _Db.Tables
Dim _tct As Integer = _Tbls.Count
Dim _i As Integer = 0
For i = 0 To _tct - 1
If Not _Tbls(i).IsSystemObject Then
_i += 1
_Tables.Add(New TableTyping() With {
.ID = _i,
.Name = _Tbls(i).Name,
.Schema = _Tbls(i).Schema,
.Columns = ProcessColumns(_Tbls(i).Columns)})
End If
Next
_TCount = _Tables.Count
End Sub
_Tables is a List(of TableTyping)
How can I do the Include? check inside the GenerateTyping procedure?
I had to change my checkbox template to the following:
<CheckBox Tag="{Binding ID}" HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding Include, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Name="ckTblInclude" />
And change the _Tables list to populate via:
Private Sub GrabTables()
Dim _Db As Database = Srv.Databases(DBName)
Dim _Tbls As TableCollection = _Db.Tables
Dim _tct As Integer = _Tbls.Count
Dim _i As Integer = 0
For i = 0 To _tct - 1
If Not _Tbls(i).IsSystemObject Then
_i += 1
_Tables.Add(New TableTyping() With {
.ID = _i,
.Name = _Tbls(i).Name,
.Schema = _Tbls(i).Schema,
.Columns = ProcessColumns(_Tbls(i).Columns),
.Include = True})
End If
Next
_TCount = _Tables.Count
End Sub

WPF: Image in ListView is not be shown

I have a ListView which should contain per line an image and text. The binding of the text works fine, but the image is not be shown.
My XAML-Markup:
<ListView Name="lvUpgrade">
<ListView.View>
<GridView>
<GridViewColumn Width="20px">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Path=Icon}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="75px" DisplayMemberBinding="{Binding Path=Time, StringFormat={}{0:HH:mm:ss}}" />
<GridViewColumn Width="300px" Header="Nachricht" DisplayMemberBinding="{Binding Path=Message}" />
</GridView>
</ListView.View>
</ListView>
My code behind:
Public Class Upgrade
Public Sub AddMessage(ByVal message As Message)
Me.lvUpgrade.Items.Add(message)
End Sub
Public Class Message
Public Enum MessageType
Normal
Information
Warning
[Error]
End Enum
Public Sub New(ByVal type As MessageType, ByVal message As String)
_Type = type
_Message = message
End Sub
Private _Type As MessageType = MessageType.Normal
Public ReadOnly Property Type As MessageType
Get
Return _Type
End Get
End Property
Private _Message As String = String.Empty
Public ReadOnly Property Message As String
Get
Return _Message
End Get
End Property
Private _Time As DateTime = Now
Public ReadOnly Property Time As DateTime
Get
Return _Time
End Get
End Property
Public ReadOnly Property Icon As System.Drawing.Image
Get
Select Case Me.Type
Case MessageType.Information
Return My.Resources.Information16
Case MessageType.Warning
Return My.Resources.Alert16
Case MessageType.Error
Return My.Resources.Error16
Case Else
End Select
Return Nothing
End Get
End Property
End Class
End Class
To bind the image I use a property which returns the image from the local resources. I use the same way to bind the image to the control like I do it for the text. Is this try wrong or why does it not works?
Thanks for any response.
You have to Convert the Image to a BitmapImage:
For this you could define the following Extension in a separate Module.
This offers the opportunity to use the Function on every Image you will have in your code:
Module Extensions
<Extension()>
Public Function ToBitmapImage(ByVal lBitmap As Bitmap) As BitmapImage
Dim lMemoryStream As New MemoryStream()
Dim lBitmapImage As New BitmapImage()
lBitmap.Save(lMemoryStream, ImageFormat.Png)
lBitmapImage.BeginInit()
lBitmapImage.StreamSource = New MemoryStream(lMemoryStream.ToArray())
lBitmapImage.EndInit()
Return lBitmapImage
End Function
End Module
After that you have to edit your property like:
Public ReadOnly Property Icon As BitmapImage
Get
Select Case Me.Type
Case MessageType.Information
Return My.Resources.Information16.ToBitmapImage
Case MessageType.Warning
Return My.Resources.Alert16.ToBitmapImage
Case MessageType.Error
Return My.Resources.Error16.ToBitmapImage
Case Else
End Select
Return Nothing
End Get
End Property

Treeview With One To Many Linq to SQL tables

I have a couple tables dealing with cars:
<Table(Name:="tblManufacturer")> Public Class dbManufacturers
Private _ManufacturerID As Integer
<Column(Storage:="_ManufacturerID", DbType:="int IDENTITY NOT NULL", IsPrimaryKey:=True, IsDbGenerated:=True, Name:="ManufacturerID")> _
Public Property ManufacturerID() As Integer
Get
Return Me._ManufacturerID
End Get
Set(value As Integer)
Me._ManufacturerID = value
End Set
End Property
Private _ManufacturerName As String
<Column(Storage:="_ManufacturerName", DbType:="Varchar(50)", Name:="ManufacturerName")> _
Public Property ManufacturerName() As String
Get
Return Me._ManufacturerName
End Get
Set(value As String)
Me._ManufacturerName = value
End Set
End Property
Private _Models As EntitySet(Of dbModels) = New EntitySet(Of dbModels)
<Association(Storage:="_Models", DeleteRule:="CASCADE", OtherKey:="ManufacturerID")> _
Public Property Models As EntitySet(Of dbModels)
Get
Return _Models
End Get
Set(value As EntitySet(Of dbModels))
_Models.Assign(value)
End Set
End Property
End Class
<Table(Name:="tblModels")> Public Class dbModels
Private _ModelID As Integer
<Column(Storage:="_ModelID", DbType:="int IDENTITY NOT NULL", IsPrimaryKey:=True, IsDbGenerated:=True, Name:="ModelID")> _
Public Property ModelID() As Integer
Get
Return Me._ModelID
End Get
Set(value As Integer)
Me._ModelID = value
End Set
End Property
Private _ManufacturerID As Integer
<Column(Storage:="_ManufacturerID", DbType:="int", Name:="ManufacturerID")> _
Public Property ManufacturerID() As Integer
Get
Return Me._ManufacturerID
End Get
Set(value As Integer)
Me._ManufacturerID = value
End Set
End Property
Private _ModelName As String
<Column(Storage:="_ModelName", DbType:="Varchar(200)", Name:="ModelName")> _
Public Property ModelName() As String
Get
Return Me._ModelName
End Get
Set(value As String)
Me._ModelName = value
End Set
End Property
End Class
The XAML:
<TreeView Name="TreeView1" Margin="3" ItemsSource="{Binding ElementName=ManufacturerInfo, Path=tblManufacturers}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate>
<TextBlock Text="{Binding Path=ManufacturerName}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Source=Models, Path=ModelName}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
The code behind:
Public Class ManufacturerInfo
Private LinqDB As New DataContext(My.Settings.dbConnection)
Property tblManufacturers As Table(Of dbManufacturers) = LinqDB.GetTable(Of dbManufacturers)()
Public Sub New()
InitializeComponent()
End Sub
Private Sub ManufacturerInfo_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Me.DataContext = Me
End Sub
End Class
So I get the list of Manufacturers, but not the nested models. Is there a way to make this work, or do I have to change how I'm doing my LINQ query?
I'm having trouble finding similar treeview examples.
Figured it out.
Still have a bit to learn about the subtle art of data binding.
<TreeView Name="TreeView1" Margin="3" ItemsSource="{Binding ElementName=ManufacturerInfo, Path=tblManufacturers}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Models}">
<TextBlock Text="{Binding Path=ManufacturerName}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=ModelName}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

Resources