Multi level data Binding in Windows Phone 8 - c#

I am a beginner in Windows phone programming.
I want to bind the data from API to my XAML elements using that Binding Attributes. Please let me know how can we bind multilevel classes objects in it.
Here's my scenario.
List<Sample> SearchResult = new List<Sample>()
{
new Sample(){
Name="ABC",
modelProperty = new SampleDetail(){
articleNo="1", videoURL = "https://www.youtube.com/watch?v=abc",
colors = new List<ColorsDemo>(){
new ColorsDemo {
Name = "Red",
colorProperty= new ColorDemoProperty{ name = "ABC",article_no = "Art1",
image = new Uri("http://img.youtube.com/vi/e60E99tUdxs/default.jpg",UriKind.RelativeOrAbsolute)
}
}
}
}
}
And now, I want to bind the Name of ColorsDemo class into my textblock. See what I have done to bind in XAML like this:
<TextBlock x:Name="PName" Grid.Row="0" Margin="100,0,0,0" Tap="ProductName_Tap" HorizontalAlignment="Center" VerticalAlignment="Center" Width="350" TextWrapping="Wrap" Foreground="Black" Text="{Binding Path=modelProperty.colors.Name}" FontSize="30"></TextBlock>

From your code, i see that colors is a List of ColorDemo objects. So when you say {Binding Path=modelProperty.colors.Name}it does not tell which list item to bind to. The correct usage should be {Binding Path=modelProperty.colors[0].Name}. This tells the control to bind to the name of the first color item (as index is 0).
To bind all the colors. You should use a Listview and bind the colors in it. So you should be able to do something like this.
<ListView ItemSource={Binding Path=modelProperty.colors}>
<ListView.ItemTemplate>
<TextBlock x:Name="PName" Grid.Row="0" Margin="100,0,0,0" Tap="ProductName_Tap" HorizontalAlignment="Center" VerticalAlignment="Center" Width="350" TextWrapping="Wrap" Foreground="Black" Text="{Binding Path=Name}" FontSize="30"></TextBlock>
</ListView.ItemTemplate>
</ListView>

Related

How do I get the pixel locations of text and other elements in a UWP ListView?

I have a ListView in my UWP app with an ItemTemplate that consists of a Path geometry and a TextBox:
<ListView
x:Name="ListView"
CanDragItems="True"
CanReorderItems="True"
ItemsSource="{x:Bind Categories}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="myData:Category">
<StackPanel
Orientation="Horizontal"
ToolTipService.ToolTip="{x:Bind CategoryString, Mode=OneWay}">
<Path
Margin="14, 10, 4, 0"
Width="10"
Height="10"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Data="{x:Bind SymbolGeometry, Mode=OneWay}"
Fill="{x:Bind Colour, Mode=OneWay}"/>
<TextBox
BorderThickness="0"
Background="Transparent"
Text="{x:Bind LegendLabel, Mode=TwoWay}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As part of exporting a piece of the UI to an SVG I would like to find the locations (in pixel coordinates relative to any parent item) of the TextBox text and Path geometry for each item in the ListView. Does anybody know how to achieve this? As the ListView items are dependant on user input I'm unsure how to retrieve the necessary information.
I'm aware UIElements can be converted to bitmaps for export, however this does not fulfil the requirements of the app.
You could use the UIElement.TransformToVisual(UIElement) Method and GeneralTransform.TransformPoint(Point) Method to get the locations of UIElement objects.
Please check the following code:
for(int i=0;i<ListView.Items.Count;i++)
{
var item = ListView.ContainerFromIndex(i) as ListViewItem;
var path = VisualTreeHelper.GetChild(item.ContentTemplateRoot as DependencyObject, 0) as Windows.UI.Xaml.Shapes.Path;
var box = VisualTreeHelper.GetChild(item.ContentTemplateRoot as DependencyObject, 1) as TextBox;
var visual1 = path.TransformToVisual(ListView); //Select the ListView control as the parent element.
var point = visual1.TransformPoint(new Point(0, 0));
var visual2 = box.TransformToVisual(ListView);
var point2 = visual2.TransformPoint(new Point(0, 0));
}

Accessing TextBox Text Inside GridView (C# / XAML)

So I have a customised GridView with a data template that contains a TextBox and is populated by a list of a custom class called Player. I need to be able to retrieve both the instance of Player and the text in the TextBox and save them to a new custom class called Score.
<GridView x:Name="gridScore" ItemsSource="{x:Bind PlayerList}" IsItemClickEnabled="True">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Player">
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtbxGridScore" TextChanged="txtbxGridScoreChangedEventHandler" />
<Image Source="{x:Bind ProfilePicture}"/>
<StackPanel VerticalAlignment="Center">
<TextBlock Text="{x:Bind FullName}" />
<TextBlock Text="{x:Bind Alias}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<Button x:Name="buttonSave" Content="Save Scores" Style="{StaticResource BarButtonStyle}" Click="buttonSave_Click"/>
I come from a web-based Java background so this is a little bit new to me but it seems like it should be a fairly simple exercise.
Initially, I tried iterating through the GridView upon a Button Click and grabbing each Player item along with the TextBox Text and saving them to a List<> of Score, however, getting the TextBox value proved troublesome.
I then tried initialising a page scope List<> of Score and simply updating it each time the TextBox value was changed, however, I wasn't able to make this work either.
A solution for either approach will work fine for my purposes. Any input is appreciated!
If I correctly understood you this is one of the way to resolve your problem.
So let's assume that your model class Player have this structure:
public class Player {
public int PlayerID { get; set; }
public string ProfilePicture { get; set; }
public string FullName { get; set; }
public string Alias { get; set; }
public float PlayerScore { get; set; } // To store textbox value
}
So you can resolve this by using two way binding.
XAML part will look something like this:
<GridView x:Name="gridScore"
ItemsSource="{x:Bind PlayerList}"
IsItemClickEnabled="True">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Player">
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtbxGridScore"
Text="{x:Bind PlayerScore, Mode=TwoWay}" />
<Image Source="{x:Bind ProfilePicture}" />
<StackPanel VerticalAlignment="Center">
<TextBlock Text="{x:Bind FullName}" />
<TextBlock Text="{x:Bind Alias}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<Button x:Name="buttonSave"
Content="Save Scores"
Click="buttonSave_Click" />
I have initialized your PlayerList with some dummy data like this:
PlayerList = new ObservableCollection<Player>() {
new Player() {
FullName = "Player A", Alias = "AAA"
},
new Player () {
FullName = "Player B", Alias = "BBB"
}
};
As you can see in XAML I am binding your text box with PlayerScore property of Player model.
When I run this App I get screen like this:
I will input some data into TextBox and click Save button:
When I click on Save it will trigger the event that you wrote in Button part
In that event I have one foreach loop that will iterate through the list and one breakpoint and as you can see on first item "Player A" the PlayerScore value is 10:
Now you can find your players with some ID property or with some other way that you want. This is the most simple way to accomplish what you want.
Remark: This could be solved in a better way using MVVM pattern and other stuff but as you mentioned you are beginner so maybe it is better for you to solve it like this and after that go with more advanced technique. Hope that this was helpful for you.

how to bind tweetinvi xaml listview?

I'am new to tweetinvi, and now i'm stuck with databinding. it's doable to retrieve tweets and i can show up the last one in a TextBlock in my XAML. but now i like to have it in a list or gridview.
code to retrieve tweets
var homeTimelineTweets = authenticatedUser.GetHomeTimeline();
foreach (var tweet in homeTimelineTweets)
{
textBlock.Text = tweet.Text;
//textBlock.Text = tweet.CreatedBy.ScreenName;
//textBlock.Text = tweet.CreatedBy.Name + ", " +tweet.Text;
//textBlock.Text = tweet.Text;
}
Code for Xaml
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="textBlock"
HorizontalAlignment="Left"
TextWrapping="Wrap"
Text="TextBlock"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
i know i have to set x:bind and x:data ... but i can figure out how?

MVVM SelectedValue from ComboBox returns Null

I have a problem. I have a car class with string brand, string model,..
I also have a view with a ComboBox containing Data. When I select an item from the ComboBox "carBrand" or the ComboBox "carModel" and click on a button, I want to create a new car object. But after clicking on the button, the carBrand.SelectedValue.ToString() is delivering a Null value, same for carModel, although I selected an item from the ComboBox.
In my VMClass:
Add a1 = new Add();
c_car m1 = param as c_car;
a1.DataContext = m1;
a1.ShowDialog();
if (a1.DialogResult.HasValue && a1.DialogResult.Value)
{
m1.c_brand = a1.carBrand.SelectedValue.ToString(); //causes NullReferenceException
m1.c_model = a1.carModel.SelectedValue.ToString(); //causes NullReferenceException
m1.c_year = a1.carYear.Content.ToString(); //this works perfectly
m1.c_km = Int32.Parse(a1.carKm.Content.ToString()); //this also works properly
//...
}
Now my View Class:
<!--CarModel ComboBox-->
<ComboBox x:Name="carModel" Style="{StaticResource combobox}" Grid.Column="1"
Margin="20,15,17,14"
ItemsSource="{Binding ModelSelectedBrand}" DisplayMemberPath="c_model" MouseLeave="carModel_MouseLeave"
Grid.Row="2" VerticalAlignment="Center" Height="30" MouseDoubleClick="carModel_MouseDoubleClick">
</ComboBox>
<!--CarYear EditableLabel-->
<Label x:Name="carYear" Content="{Binding ElementName=carModel, Path=SelectedValue.c_year}" Margin="20,14,17,14"
Style="{StaticResource EditableLabelStyle}" Foreground="White"
Grid.Column="1" Grid.Row="5" VerticalAlignment="Center" Height="30">
</Label>
<!--CarKM EditableLabel-->
<Label x:Name="carKm"
Content="{Binding ElementName=carModel, Path=SelectedItem.c_km}" Style="{StaticResource EditableLabelStyle}"
Margin="20,14,17,14"
Grid.Column="1" Grid.Row="3" Foreground="White" VerticalAlignment="Center" Height="30">
</Label>
I hope someone can help me fixing this issue.
Thanks in advance!
So the simple answer (I think, I haven't tested yet) is that there isn't a SelectedValuePath set on your ComboBox (As stated by vesan in the comments).
This means that SelectedValue will always be null.
You could use SelectedItem to return the selected Car and then get the property from that or just set the SelectedValuePath on the ComboBox.
Now, this could of course be made better by using bindings but that is up to you whether you want to implement this.

ObservableCollection from Linq

Can someone see what I need to change here? I am displaying an observablecollection of AddressTypeClass items. The object items show up in the listbox instead of the data. I can see the data in the objects in debug mode.
THE XAML.CS FILE:
DataContext MyTableDataContext = new MyTableDataContext();
ObservableCollection<AddressTypeClass> theOC = new ObservableCollection<AddressTypeClass>(new MyTableDataContext().AddressTypes.AsEnumerable()
.Select(lt => new AddressTypeClass
{
AddressTypeID = lt.AddressTypeID,
AddressType = lt.AddressType,
})
.ToList());
this.listBox1.ItemsSource = theOC;
THE XAML FILE:
<ListBox Name="listBox1" Margin="8" Height ="200" Width ="150" FontSize="12" Foreground="#FF2F3806" ItemsSource="{Binding AddressType}" IsSynchronizedWithCurrentItem="True" >
</ListBox>
You need to add an ItemTemplate to your ListBox, e.g.
<ListBox Name="listBox1" Margin="8" Height ="200" Width ="150" FontSize="12" Foreground="#FF2F3806" ItemsSource="{Binding AddressType}" IsSynchronizedWithCurrentItem="True" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=AddressType}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You can impove your code by using my ObservableComputations library. In your code you manualy update theOC every time MyTableDataContext.AddressTypes dbSet (I assume you are using EntityFramework) changes (new item or remove) or properties (AddressType.AddressTypeID, AddressType.AddressType) changes. Using AddressType you can automate that process:
DataContext MyTableDataContext = new MyTableDataContext();
ObservableCollection<AddressTypeClass> theOC = MyTableDataContext.AddressTypes.Local
.Selecting(lt => new AddressTypeClass
{
AddressTypeID = lt.AddressTypeID,
AddressType = lt.AddressType,
});
this.listBox1.ItemsSource = theOC;
theOC is ObservableCollection and reflects all the changes in the MyTableDataContext.AddressTypes.Local collection and properties mentioned in the code above. Ensure that all properties mentioned in the code above notify of changes through the INotifyProperytChanged interface.

Categories