Xaml Data Binding - vb.net

I have the below xaml that I am trying to bind to my class. I am having trouble getting the values to show up. Can anyone point me in the direction of what I am missing. Thank you in advance.
Dim frm As New EditPart
frm.DataContext = New SelectedPart(_CPPartPicker.Selected_Part, "ABC")
frm.Show()
Class SelectedPart
Property Part_Key As Integer
Property Part_Id As String
Property Part_Rev As String
Property Whse As String
Property Part_Description As String
Sub New(Part As SNC.SL.Common.CP_Item.CP_Item_Lookup_Version_1Item_Lookup_Response, Whse As String)
Part_Key = Part.ITEM_KEY
Part_Id = Part.ITEM_ID
Part_Rev = Part.ITEM_RVSN_ID
Whse = Whse
Part_Description = Part.ITEM_DESC
End Sub
End Class
<Grid x:Name="LayoutRoot" Margin="2">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<sdk:Label Content="{Binding Path=Part_Id, StringFormat='Part ID: \{0}'}" />
<sdk:Label Content="{Binding Path=Part_Rev, StringFormat='Part Rev: \{0}'}" />
<sdk:Label Content="{Binding Path=Part_Description, StringFormat='Description: \{0}'}"/>
<Button x:Name="CancelButton" Content="Cancel" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
<Button x:Name="OKButton" Content="OK" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" />
</Grid>
In the ouput window I get the below error message:
Cannot get 'Part_Id' value (type 'System.String') from 'SNC.CommonStock.SelectedPart' (type 'SNC.CommonStock.SelectedPart'). BindingExpression: Path='Part_Id' DataItem='SNC.CommonStock.SelectedPart' (HashCode=53866394); target element is 'System.Windows.Controls.Label' (Name=''); target property is 'Content' (type 'System.Object').. System.MethodAccessException: Attempt by method 'System.Windows.CLRPropertyListener.get_Value()' to access method 'SNC.CommonStock.SelectedPart.get_Part_Id()' failed.

The labels are all on top of one another at present, if there is no description then potentially you'll see no content. Place the labels in a StackPanel.

I had to make the class I was binding to public

Related

MasterDetail ListView and editable ContentPresenter: what is wrong?

I'm based on the official Microsoft sample to create a MasterDetail ListView:
MasterDetail ListView UWP sample
I have adapted it to my case, as I want that users can edit directly selected items from the ListView. But I meet a strange comportement:
when I add a new item to the ListView, the changes of the current item, done in the details container, are well saved
but when I select an existing item in the ListView, the changes of the current item, done in the details container, are not saved
Here is a screenshot of my app:
The XAML of my ListView is like this:
<!-- Master : List of Feedbacks -->
<ListView
x:Name="MasterListViewFeedbacks"
Grid.Row="1"
ItemContainerTransitions="{x:Null}"
ItemTemplate="{StaticResource MasterListViewFeedbacksItemTemplate}"
IsItemClickEnabled="True"
ItemsSource="{Binding CarForm.feedback_comments}"
SelectedItem="{Binding SelectedFeedback, Mode=TwoWay}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.FooterTemplate>
<DataTemplate>
<CommandBar Background="White">
<CommandBar.Content>
<StackPanel Orientation="Horizontal">
<AppBarButton Icon="Add" Label="Add Feedback"
Command="{Binding AddItemFeedbacksCommand}" />
<AppBarButton Icon="Delete" Label="Delete Feedback"
Command="{Binding RemoveItemFeedbacksCommand}" />
</StackPanel>
</CommandBar.Content>
</CommandBar>
</DataTemplate>
</ListView.FooterTemplate>
</ListView>
The XAML of the ListView's ItemTemplate is:
<DataTemplate x:Key="MasterListViewFeedbacksItemTemplate" x:DataType="models:Feedback_Comments">
<StackPanel Margin="0,11,0,13"
Orientation="Horizontal">
<TextBlock Text="{x:Bind creator }"
Style="{ThemeResource BaseTextBlockStyle}" />
<TextBlock Text=" - " />
<TextBlock Text="{x:Bind comment_date }"
Margin="12,1,0,0" />
</StackPanel>
</DataTemplate>
The XAML of the Details container is like this:
<!-- Detail : Selected Feedback -->
<ContentPresenter
x:Name="DetailFeedbackContentPresenter"
Grid.Column="1"
Grid.RowSpan="2"
BorderThickness="1,0,0,0"
Padding="24,0"
BorderBrush="{ThemeResource SystemControlForegroundBaseLowBrush}"
Content="{x:Bind MasterListViewFeedbacks.SelectedItem, Mode=OneWay}">
<ContentPresenter.ContentTemplate>
<DataTemplate x:DataType="models:Feedback_Comments">
<StackPanel Visibility="{Binding FeedbacksCnt, Converter={StaticResource CountToVisibilityConverter}}">
<TextBox Text="{Binding creator, Mode=TwoWay}" />
<DatePicker Date="{Binding comment_date, Converter={StaticResource DateTimeToDateTimeOffsetConverter}, Mode=TwoWay}"/>
<TextBox TextWrapping="Wrap" AcceptsReturn="True" IsSpellCheckEnabled="True"
Text="{Binding comment, Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ContentPresenter.ContentTemplate>
<ContentPresenter.ContentTransitions>
<!-- Empty by default. See MasterListView_ItemClick -->
<TransitionCollection />
</ContentPresenter.ContentTransitions>
</ContentPresenter>
The "CarForm" is the main object of my ViewModel. Each CarForm contains a List of "Feedback_Comments".
So in my ViewModel, I do this when I add a new comment:
private void AddItemFeedbacks()
{
FeedbacksCnt++;
CarForm.feedback_comments.Add(new Feedback_Comments()
{
sequence = FeedbacksCnt,
creator_id = user_id,
_creator = username,
comment_date = DateTime.Now
});
SelectedFeedback = CarForm.feedback_comments[CarForm.feedback_comments.Count - 1];
}
=> the changes done in the Feedback_Comment that was edited before the add are well preserved
I don't do anything when the user select an existing Feedback_Comment: this is managed by the XAML directly.
=> the changes done in the Feedback_Comment that was edited before to select anoter one are not preserved
=> Would you have any explanation?
The TwoWay binding for the Text property is updated only when the TextBox loses focus. However, when you select a different item in the list, the contents of the TextBox are no longer bound to the original item and so are not updated.
To trigger the update each time the Text contents change, so that the changes are reflected immediately, set the UpdateSourceTrigger set to PropertyChanged:
<TextBox Text="{Binding comment, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
Triggering changes everywhere
To ensure your changes are relflected everywhere including the list, you will need to do two things.
First, your feedback_comments is of type ObservableCollection<Feedback_Comments>. This ensures that the added and removed items are added and removed from the ListView.
Second, the Feedback_Comments class must implement the INotifyPropertyChanged interface. This interface is required to let the user interface know about changes in the data-bound object properties.
Implementing this interface is fairly straightforward and is described for example on MSDN.
The quick solution looks like this:
public class Feedback_Comments : INotifyPropertyChanged
{
// your code
//INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged( [ CallerMemberName ]string propertyName = "" )
{
PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
}
Now from each of your property setters call OnPropertyChanged(); after setting the value:
private string _comment = "";
public string Comment
{
get
{
return _comment;
}
set
{
_comment = value;
OnPropertyChanged();
}
}
Note, that the [CallerMemberName] attribute tells the compiler to replace the parameter by the name of the caller - in this case the name of the property, which is exactly what you need.
Also note, that you can't use simple auto-properties in this case (because you need to call the OnPropertyChanged method.
Bonus
Finally as a small recommendation, I see you are using C++-like naming conventions, which does not fit too well into the C# world. Take a look at the recommended C# naming conventions to improve the code readability :-) .

Databinding of ObservableCollection to TextBoxes in Tab

I started writing an application and I am facing trouble with the databinding of an observablecollection, because I am not very familiar with WPF an Binding. Further the different method of binding like object binding, xaml binding are confusing me.
The idea is to retrieve data from a SQL statement and add them to a observablecollection. Afterwards textboxes/comboboxes which are located in a tab in the mainwindows should be updated with this data.
I have a SQL Class which is retrieving the data from a sqlserver and populating the observablecollection. The following code is working at the moment:
Imports System.Data.Sql
Imports System.Data.SqlClient
Imports System.Data
Imports System.Collections.ObjectModel
Imports System.Xml
Imports System.Xml.Linq
Public Class SQLQueries
Public Sub GetPersonData(ByVal HRID_TextBox_OnB As String)
Dim con As New SqlConnection(My.Settings.AppConnString.ToString) 'connectionstring is retrieved from app settings
Dim cmd As New SqlCommand(QPersonDataQuery & "and person.personnelnumber = #DBG_HRID", con)
cmd.Parameters.AddWithValue("#DBG_HRID", HRID_TextBox_OnB)
Dim PersonData As New ObservableCollection(Of String) PersonData.Clear()
Try
con.Open()
Dim reader As SqlDataReader = cmd.ExecuteReader()
If (reader.HasRows) Then
While (reader.Read())
For i = 0 To reader.FieldCount - 1
PersonData.Add(i)
Next i
End While
End If
Catch ex As Exception
MessageBox.Show("Better call Saul!!" & vbCrLf & vbCrLf + ex.Message)
Finally
If con.State <> ConnectionState.Closed Then con.Close()
End Try
con.Dispose()
End Sub
End Class
My XAML is looking like this at the moment:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="FAT Client Primary Access" Height="609" Width="811" Background="White">
<Grid>
<Menu IsMainMenu="True" Height="28" VerticalAlignment="Top" Background="White">
<MenuItem Header="_File">
<MenuItem Header="_Close" Click="CloseApp_Click"/>
</MenuItem>
<MenuItem Header="_Database">
<MenuItem Header="_Check Connection" Click="CheckConnection_Click"/>
<MenuItem Header="_Change Connection String" Click="ChangeConnection_Click"/>
</MenuItem>
</Menu>
<TabControl Height="544" HorizontalAlignment="Left" Margin="0,26,0,0" Name="TabControl1" VerticalAlignment="Top" Width="789" Background="White">
<TabItem Header="Onboarding" Name="TabItem1" Background="White">
<Grid Background="White" Width="797" Height="524">
<Label Content="HRID" Height="27" HorizontalAlignment="Left" Margin="32,24,0,0" Name="Label1" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="74,24,0,0" Name="TextBox1" VerticalAlignment="Top" Width="83" />
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="182,23,0,0" Name="Button1" VerticalAlignment="Top" Width="75" />
<TextBox Height="26" HorizontalAlignment="Left" Margin="158,104,0,0" Name="TextBox2" VerticalAlignment="Top" Width="124" />
</Grid>
</TabItem>
<TabItem Header="other Trigger" Name="TabItem2" Background="White">
<Grid Background="White" />
</TabItem>
</TabControl>
</Grid>
</Window>
Unfortunately I have no idea how to bind the first value in my observablecollection to textbox2. I tried and read a lot but this was more confusing then helping out.
Do I need a separate Class to bind the observablecollection to the textboxes?
I would appreciate it if could give a me small hint.
Thanks in advance. And also Hello everybody.
<TextBox x:Name="textBox2" Text="{Binding [2].Name}" />
This binding path will show Name property of 3rd element of your ObservableCollection.
<TextBox x:Name="textBox2" Text="{Binding [0].Name}" />
So, this will show Name of first element of your collection.
But how Textbox will know what is the collection to use ? For that you have to set DataContext either at root level, or at your TextBox level. This root can be anywhere above your TextBox. DataContext set at this root will be visible within all children of this root only.
Your data can be complex like Country>States>City.For example, you can set DataContext to Country at root level, and some child elements can then use States, while some can use City etc.
So, set DataContext like this :
Imports System.Collections.ObjectModel
Class MainWindow
Public Property InvoiceCollection As New ObservableCollection(Of Invoice)
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Fill your InvoiceCollection.
...
...
Me.DataContext = InvoiceCollection
End Sub
End Class
Then you can show TotalPrice of first Invoice item like :
<TextBox x:Name="textBox2" Text="{Binding [0].TotalPrice}" />
You can even set DataContext of TextBox2 like :
TextBox2.DataContext = InvoiceCollection[0]
then databinding will look like :
<TextBox x:Name="textBox2" Text="{Binding TotalPrice}" />
You can even set DataContext of TextBox2 like :
TextBox2.DataContext = InvoiceCollection
then databinding will look like :
<TextBox x:Name="textBox2" Text="{Binding [0].TotalPrice}" />
Few important links :
DataBinding in 7 part series
Property path syntax

how to put images on tabs (pivots) in windows 10 app

I have read most of the Windows 10 UI design guidelines and here are some pictures of examples of a pivot navigation that is essentially a tab navigation with images: https://msdn.microsoft.com/en-us/library/windows/apps/dn997788.aspx#examples
I was unable to find out how to put images on these tabes (pivotitems).
<Pivot x:Name="mainTabs">
<PivotItem x:Name="Header1" Header="Header1" Background="{x:Null}" Foreground="{x:Null}"/>
<PivotItem x:Name="Header2" Header="Header2"></PivotItem>
<PivotItem x:Name="Header3" Header="Header3"></PivotItem>
<PivotItem x:Name="Header4" Header="Header4"></PivotItem>
<PivotItem x:Name="Header5" Header="Header5"></PivotItem>
</Pivot>
HeaderTemplate works OK for replacing text with pictures but then text is missing, and I would like to keep the text like shown in Windows 10 UI guidelines.
<Pivot x:Name="mainTabs">
<Pivot.HeaderTemplate>
<DataTemplate>
<Image Source="{Binding}"></Image>
</DataTemplate>
</Pivot.HeaderTemplate>
<PivotItem x:Name="Header1" Header="Assets/play1.png"></PivotItem>
<PivotItem x:Name="Header2" Header="Assets/play2.png"></PivotItem>
</Pivot>
Nokia Developer website had some really great article about how to make a tabbed pivot headers like official Instagram or Twitter app in Windows Phone.However , that article is not available for now because Microsoft decided to ignore all of Nokia Developer content , unfortunately.
I researched a bit and found this article instead
http://depblog.weblogs.us/2013/08/29/twitterate-your-windows-phone-app/
PivotItem headers' are being used in PivotHeaderTemplate AFAIR.Basically you can follow the article above or just change your Pivot's HeaderTemplate.
Write a converter that converts your Header property to Text and returns it.
public class ImageToTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var sent = value as string;
switch(sent)
{
case "Assets/play1.png":
return "Play 1 Header";
case "Assets/play2.png":
return "Play 2 Header";
default:
return string.Empty;
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Add this converter's namespace to your XAML and define it in your Resources.Then change your template as
<DataTemplate>
<StackPanel>
<Image Source="{Binding}"></Image>
<TextBlock Text="{Binding Source='',Converter={StaticResource ImageToTextConverter}}" />
</StackPanel>
</DataTemplate>
I know this post is old and no one likes to kick a dead horse, but I figured I might share my solution that doesn't rely on a value converter and allows you to simply set an image with text. Just for anyone who is looking to add images or anything to a pivot item since there does not seam to be a simple solution out there.
Add a stack panel to the pivot item header with image and text. That's it.
<Pivot x:Name="Tabs" Grid.Row="1" Grid.Column="0" >
<PivotItem>
<PivotItem.Header>
<StackPanel VerticalAlignment="Top">
<Image Width="25" Height="25" Source="../Assets/Home.png"/>
<TextBlock Text="Home Tab"/>
</StackPanel>
</PivotItem.Header>
<Grid>
<TextBlock Text="asdfasfasdfasdfasdf"/>
</Grid>
</PivotItem>
<PivotItem>
<PivotItem.Header>
<StackPanel VerticalAlignment="Top">
<Image Width="25" Height="25" Source="../Assets/Schedule.png"/>
<TextBlock Text="Home Tab"/>
</StackPanel>
</PivotItem.Header>
<Grid>
<TextBlock Text="134123475"/>
</Grid>
</PivotItem>
</Pivot>

How to call command inside listbox in silverlight4

I am using Listbox and it contains button ,and i want to handle button click event using command.but my command never calls.
is this Correct way??
<pmControls:pmListBox Grid.Row="1" Margin="3" ItemsSource="{Binding Countries}" SelectedItem="{Binding SelectedCountry}" >
<pmControls:pmListBox.ItemTemplate >
<DataTemplate >
<Button Command="{Binding GetAllStatesCommand}" CommandParameter="{Binding}" Margin="3" Width="100" Height="50" Content="{Binding Title}">
</Button>
</DataTemplate>
</pmControls:pmListBox.ItemTemplate>
</pmControls:pmListBox>
The DataContext of one list item is different from the DataContextof the surrounding control. To bind that command to the DataContext of that control you have two options:
Either you provide the control with a name and reference to that:
<pmControls:pmListBox x:Name="myCoolListBox" [...]>
<pmControls:pmListBox.ItemTemplate>
<DataTemplate>
<Button Command="{Binding DataContext.GetAllStatesCommand, ElementName=myCoolListBox}" CommandParameter="{Binding}" [...] />
</DataTemplate>
</pmControls:pmListBox.ItemTemplate>
</pmControls:pmListBox>
Or you create class holding your DataContext...
public class DataContextBinder : DependencyObject
{
public static readonly DependencyProperty ContextProperty = DependencyProperty.Register("Context", typeof(object), typeof(DataContextBinder), new PropertyMetadata(null));
public object Context
{
get { return GetValue(ContextProperty); }
set { SetValue(ContextProperty, value); }
}
}
...and create an instance of that in the resources section of your ListBox:
<pmControls:pmListBox x:Name="myCoolListBox" [...]>
<pmControls:pmListBox.Resources>
<local:DataContextBinder x:Key="dataContextBinder" Context="{Binding}" />
</pmControls:pmListBox.Resources>
<pmControls:pmListBox.ItemTemplate>
<DataTemplate>
<Button Command="{Binding Context.GetAllStatesCommand, Source={StaticResource dataContextBinder}" CommandParameter="{Binding}" [...] />
</DataTemplate>
</pmControls:pmListBox.ItemTemplate>
</pmControls:pmListBox>

How to use trigger event in a button inside a datagrid in silverlight using relaycommand mvvm

How to use trigger event in a button inside a datagrid in silverlight using relaycommand mvvm
Iam unable to get selected values in to some Dto , it means once i selected a row for delete , the selected item property showing NULL .how to solve it pls
You can use trigger event like below in datagrid:
<Button Content="Message" Height="23" HorizontalAlignment="Left" Margin="234,116,0,0" Name="btnMsg" VerticalAlignment="Top" Width="75" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<si:CallDataMethod Method="HandleShowMessage"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
You have to add necessary reference for this.
For selecteditem you have to set selected item into datagrid and other thing you have to decalre a property in viewmodel:
In Xaml:
<sdk:DataGrid Height="Auto" AutoGenerateColumns="False" ItemsSource="{Binding Emp}" SelectedItem="{Binding SelectedEMp,Mode=TwoWay}" BorderThickness="1" HorizontalAlignment="Left" Name="dataGrid1" VerticalAlignment="Top" Width="auto">
and in Viewmodel:
private EmpInfo _selectedEMp;
public EmpInfo SelectedEMp
{
get { return _selectedEMp; }
set
{
_selectedEMp = value;
on("SelectedEMp");
}
}
Thanks