Bind count of pushpins on the Map to TextBlock - c#

I have two controls in a Stack Panel - Map and TextBlock. Collection of pushpins on a map changes dynamically. So I need TextBlock to display current Count of items in pushpins collection.
What is a right approach to bind ItemsSource.Length to TextBlock.Text? Somehow like this:
<maps:Map Name="MainMap">
<toolkit:MapExtensions.Children>
<toolkit:MapItemsControl Name="BusItems">
<toolkit:MapItemsControl.ItemTemplate>
<DataTemplate>
<toolkit:Pushpin GeoCoordinate="{Binding Coordinates}" Content="{Binding Value}"/>
</DataTemplate>
</toolkit:MapItemsControl.ItemTemplate>
</toolkit:MapItemsControl>
</toolkit:MapExtensions.Children>
</maps:Map>
<TextBlock Text="{Binding Items.Count, ElementName=BusItems}"></TextBlock>

You cannot bind to Items.Count, because it is a method not a property, so create a property exposing Items.Count() like so:
public int PushpinCount
{
get { return Items.Count(); }
}
and bind to PushpinCount instead.

Related

How to get ListView item index from custom ViewCell in Xamarin Forms?

I created a ListView that have a custom ViewCell as below:
<ListView x:Name="ListView1" ItemTapped="ListView1_ItemTapped"
SeparatorVisibility="None" RowHeight="192" HasUnevenRows="False"
FlowDirection="RightToLeft" CachingStrategy="RecycleElement" >
<ListView.ItemTemplate>
<DataTemplate>
<custom:ViewCell1 />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and here is the XAML for the custom ViewCell
<ViewCell.View>
<StackLayout>
<Label Text="{Binding Name}" />
<Label Text="{Binding ID}" />
<Button x:Name="Button1" Text="Get index" Clicked="Button1_Clicked" />
</StackLayout>
</ViewCell.View>
All I need is when I click on Button1, I get the ListView1 item index (or ViewCell index)
The problem is I can't access ListView1 from Button1_Clicked event from the code behind in the custom ViewCell and gets tapped item index of ListView1 (or even gets ViewCell tapped item index).
I searched a lot, and found that it can be done by 3 ways:
1- Create an attached property for the ViewCell to get its index.
2- Use indexer for the ViewCell and get its index.
3- Use ITemplatedItemsView interface as mentioned in this question
But unfortunately I couldn't implement any of them from Button1_Clicked event in the custom ViewCell code behind because I'm not an expert in either MVVM or C#.
Can I have an expert assistance please.
Thanks
There are many ways which can implements it . If you are new to data binding and MVVM. I will provide the easiest way .
Firstly , add a property in the model of ItemSource .
public class YourModel
{
public int Index { get; }
//other properties like name and ID
public YourModel(int index)
{
Index = index;
}
}
And set the value of Index when init the ItemSource of ListView .
sources = new ObservableCollection<YourModel>() { };
for(int i=0;i<20;i++)
{
sources.Add(new YourModel(i) { /**other propertes**/});
}
In CustomCell
Get it like following
var model = this.BindingContext as YourModel;
int index = model.Index;
try using Button1.Parent.Parent.Parent... and so on, unless you get your listview's object.
Also pass BindingContext of viewcell in button's CommandParameter like CommandParameter={Binding} and then get the index of your received object from ItemsSource.

How to get WPF ListBox to update at start using ItemsSource?

I am very new to WPF and especially to data-binding but I'm trying to populate a ListBox with elements from an external resource, and trying to also follow the MVVM pattern. As such I am trying to avoid any code in my code-behind. I've looked over dozens of other questions similar to this but I feel I am missing something stupid as I cannot get my ListBox to generate with values. I have set the DataContext and then set the Binding for the ItemsSource to the correct property.
Question
How do I simply get this code to populate my empty ListBox when the application starts up?
XAML
<TabItem Name="ServerListTab" Header="Server List">
<TabItem.DataContext>
<viewModel:ServerListViewModel />
</TabItem.DataContext>
<ListBox
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding ServerList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
IsSynchronizedWithCurrentItem="True"
SelectedItem="{Binding SelectedServer}">
</ListBox>
</TabItem>
ServerList property in view model
public BindingList<string> ServerList
{
get { return _serverListModel.ServerList; }
set
{
if (ReferenceEquals(_serverListModel.ServerList, value)) return;
var aTestServers = //code hidden : gets array correctly from resource
for (var i = 0; i < aTestServers.Count; i++)
{
_serverListModel.ServerList.Add(aTestServers[i]);
}
InvokePropertyChanged("ServerList");
}
}

Change GridView Item DataTemplate based on seperate ViewModel Property in WinRT

What I am attempting to do is have a collection of items shown in a GridView control and have the size of these items change based on a command executed by a separate button.
For example, having a row of buttons across the top reading “Small”, “Medium” and “Large” and having the items in the GridView respond to the relevant command by displaying its items in the relevant state.
I have the gridview declared like so
<GridView ItemsSource="{Binding Squares}"
With Squares being an observable collection of Square objects that have a Title and a Fill property.
At first I went down the DataTemplateSelector route by declaring the following data templates in the Resources section of the page.
<DataTemplate x:Key="SquareSmallTemplate">
<Grid Height="100" Width="100">
<Rectangle Fill="{Binding Fill}"/>
<TextBlock Text="{Binding Title}"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="SquareMediumTemplate">
<Grid Height="150" Width="150">
<Rectangle Fill="{Binding Fill}"/>
<TextBlock Text="{Binding Title}"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="SquareLargeTemplate">
<Grid Height="200" Width="200">
<Rectangle Fill="{Binding Fill}"/>
<TextBlock Text="{Binding Title}"/>
</Grid>
</DataTemplate>
The idea being that the grid’s height and width properties are different for the relevant template. I declared the following data templates in the selector
public DataTemplate SmallTemplate { get; set; }
public DataTemplate MediumTemplate { get; set; }
public DataTemplate LargeTemplate { get; set; }
And in the SelecteTemplateCore method I just returned the relevant template
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
string value = item as string;
if (value != null)
{
if (value == "Small")
return SmallTemplate;
else if (value == "Medium")
return MediumTemplate;
else if (value == "Large")
return LargeTemplate;
return base.SelectTemplate(item, container);
}
else
{
return base.SelectTemplateCore(item, container);
}
}
However, with this method (and, by design of the DataTemplateSelector) the object being passed in is the item in the collection (the Square).
This is fine if I wanted each item to have a different appearance or something, but what I need is the template to change based on another property on the view model.
For this, I have the following
public string State {get; set;}
and this is set to “Small”, “Medium, or “Large based on a separate row of three buttons that execute a command that sets this property to the relevant value.
How do I relate the State property to changing to the relevant DataTemplate?
Another route I tried was to have a single Data template that used the VSM to animate the Height/Width properties in the relevant states. However I could not get the relevant animation to execute when the State changed.
Any help would be great, thanks
There are a few ways to do this, I'm not sure which would be best. In any case, you'll need 1) a trigger, and 2) the action to update the template. I am leaning towards using PropertyChangedTrigger along with an InvokeCommandAction.
<GridView x:Name="grid">
<i:Interaction.Triggers>
<ei:PropertyChangedTrigger Binding="{Binding State}">
<i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=UpdateTemplateCommand}" CommandParameter="{Binding State}" />
</ei:PropertyChangedTrigger>
</i:Interaction.Triggers>
<GridView>
(Here the "AncestorType" would just be the root of the view, so please change "UserControl" as needed.)
Then in the view, you would have an ICommand that updates the template:
UpdateTemplateCommand = new DelegateCommand(state => {
switch ((string)state)
{
default:
case "Small" : grid.ItemTemplate = "SquareSmallTemplate"; break;
case "Medium" : grid.ItemTemplate = "SquareMediumTemplate"; break;
case "Large" : grid.ItemTemplate = "SquareLargeTemplate"; break;
}
});
IDK ... after writing this out it seems a bit convoluted. Maybe you'd find it preferable to add a CurrentDataTemplate property to the view-model, and assign it by creating DataTemplates from strings using XamlReader.

WPF Get CheckBoxes inside ListBox in code

I have this List box and I want to search for its items which were selected (IsChecked=true) by user
<CheckBox Style="{StaticResource ResourceKey=CheckBoxes}"
Name="chkBoxSelectAllStaff" Content="Select All">
</CheckBox>
<ListBox Name="lstStaffs" MaxHeight="250" MinHeight="50" Margin="0,5,5,5" Width="350"
ScrollViewer.VerticalScrollBarVisibility="Auto" HorizontalAlignment="Right"
HorizontalContentAlignment="Right">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Style="{StaticResource ResourceKey=CheckBoxes}" IsChecked="{Binding ElementName=chkBoxSelectAllStaff, Mode=OneWay, Path=IsChecked}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}" Margin="0,0,3,0"></TextBlock>
<TextBlock Text="{Binding LastName}" Margin="0,0,3,0"></TextBlock>
<TextBlock Text="{Binding CellphoneNumber}" Margin="0,0,3,0"></TextBlock>
</StackPanel>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
I want to do something like this
foreach(var item in lstStaff.Items){
if((CheckBox) item).IsChecked){
//do something
}
}
And also I am binding the data this way :
//staff is my entity object containing Id, FirstName, LastName, CellphoneNumber
lstStaffs.ItemsSource = args.Result; // comes from webservice call and is Staff[]
lstStaffs.UpdateLayout();
But I get Staff object in lstStaffs.Items!!, So how can I iterate over selected(IsChecked=true) items(staffs) ...
Tnx
From the How to: Find DataTemplate-Generated Elements page at MSDN:
// Getting the currently selected ListBoxItem
// Note that the ListBox must have
// IsSynchronizedWithCurrentItem set to True for this to work
ListBoxItem myListBoxItem = (ListBoxItem)(myListBox.ItemContainerGenerator.
ContainerFromItem(myListBox.Items.CurrentItem));
// Getting the ContentPresenter of myListBoxItem
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
// Finding textBlock from the DataTemplate that is set on that ContentPresenter
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
TextBlock myTextBlock = (TextBlock)myDataTemplate.FindName("textBlock",
myContentPresenter);
// Do something to the DataTemplate-generated TextBlock
MessageBox.Show("The text of the TextBlock of the selected list item: "
+ myTextBlock.Text);
This shows you how to get access to elements defined in a DataTemplate. However, if you just want to get access to the items from the collection that have been selected, there is a much simpler way:
var selectedItems = lstStaffs.SelectedItems;
You must set the SelectionMode to Multiple or Extended for this to work.

Dynamically bind a textblock in a looping selector in wp7

I am developing an application where I have a class called UIManager in which there is a method which has an array of data
public void DisplayCatalog(string[] displayName, BitmapImage[] icons)
{
DisplayItem.Clear();
for (int i = 0; i < displayName.Length; i++)
{
DisplayItem.Add(new ItemList { WidgetName = displayName[i], Icon = icons[i] });
}
NotifyPropertyChanged("UI");
}
Now I want this data ie;WidgetName to be displayed in my MainPage where I have used a Looping selector.
*<custom:LoopingSelector x:Name="selectorLeft" ItemMargin="5" ItemSize="145,145" Margin="6,0,-6,22">
<custom:LoopingSelector.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding WidgetName}"/>
</StackPanel>
</DataTemplate>
</custom:LoopingSelector.ItemTemplate>
</custom:LoopingSelector>
*
Also I need to scroll the looping selector Horizontally.
How can I achieve this...??? Any valuable solutions Please.......
I have used Horizontal Looping Selector but I am not getting how to bind the data from my UIManager class on to the Horizontal Looping Selector..
<toolkit:HorizontalLoopingSelector Grid.Row="0" Margin="12" Height="128" ItemSize="128,128" ItemTemplate="{StaticResource ?????}">
<toolkit:HorizontalLoopingSelector.DataSource>
????????
</toolkit:HorizontalLoopingSelector.DataSource>
</toolkit:HorizontalLoopingSelector>
u need to create a datasource class and bind the values to the looping selector source .its similar to binding source to the vertical looping selector.
Visit http://www.windowsphonegeek.com/articles/WP7-LoopingSelector-in-depth--Part1-Visual-structure-and-API
Check out this resource if you still require a horizontal loop selector:
http://blog.supaywasi.com/2011/06/horizontal-looping-selector/

Categories

Resources