I have a ListView that have a custom view inside it ViewCell.
This custom view is a Label that render an HTML content.
All works, except when a ViewCell exit from the screen the label lost th HTML format and show the HTML tags.
This is the custom renderer in IOS (same problem on Android):
[assembly: ExportRenderer(typeof(LabelHtmlView), typeof(LabelHtmlCustomRenderer))]
namespace SgatMobileV2.iOS {
public class LabelHtmlCustomRenderer : LabelRenderer {
protected override void OnElementChanged(ElementChangedEventArgs<Label> e) {
base.OnElementChanged(e);
var View = (LabelHtmlView)Element;
if (View == null) return;
var Attribute = new NSAttributedStringDocumentAttributes();
var NsError = new NSError();
Attribute.DocumentType = NSDocumentType.HTML;
Control.AttributedText = new NSAttributedString(View.Text, Attribute, ref NsError);
}
}
}
This is the ListView code:
<ListView x:Name="ListaRigheWo" CachingStrategy="RecycleElement"
HasUnevenRows="True" SeparatorVisibility="Default"
ItemsSource="{Binding ListaWORighe}">
[...]
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
[...]
<view:LabelHtmlView
Text="{Binding DescrizioneIntervento}" Grid.Row="1" Grid.Column="2"
Grid.ColumnSpan="4" Style="{StaticResource LblValore}" />
How can I solve this?
Thank you!
Related
I have ListView which is populating Id based on username:
<Entry Text="{Binding username, Mode=TwoWay}"/>
<Button Command="{Binding SearchCommand}" />
<ListView ItemsSource="{Binding SearchId}"
HasUnevenRows="False"
x:Name="list"
ItemTapped="LstItems_OnItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<StackLayout Orientation="Vertical" >
<Label x:Name="ident"
Text="{Binding Id}"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
private async void LstItems_OnItemTapped(object sender, ItemTappedEventArgs e)
{
var item = (UserDetail)e.Item;
var newpage = new Contact(item.Id);
await Navigation.PushAsync(newpage);
}
public Command SearchCommand
{
get
{
return new Command(async () =>
{
var employeesServices = new EmployeesServices();
SearchId= await employeesServices.GetUserDetailAsync(_username);
});
}
}
private List<UserDetail> _SearchId;
public List<UserDetail> SearchId
{
get { return _SearchId; }
set
{
_SearchId = value;
OnPropertChanged();
}
}
I can successfully pass the id to another page, now I have another issue, I can only pass Id from listview to another page when I tap on the listview.
Is it possible if I click on button Id directly pass on next page without tap on ListView?
You can use SelectedItem inside your List View like this:
<ListView ItemsSource="{Binding SearchId}" HasUnevenRows="False" x:Name="list" ItemTapped="LstItems_OnItemTapped" SelectedItem="{Binding SelectedListItem,Mode=TwoWay}">
After using this you will have current selected item of your list and you can pass that to any page!
Hope this may solve your issue.
I'm making an MenuItem dynamic in a PCL project, constructing this when the list view are appearing.
This is my xaml:
<ListView x:Name="ListParceiros" RowHeight="60" ItemTapped="Parceiros_Tapped" Style="{StaticResource listViewGlobalStyle}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Appearing="OnItemAppearing">
<StackLayout Orientation="Horizontal" HorizontalOptions="Fill" BackgroundColor="#fff">
<StackLayout Orientation="Vertical">
<Label Text = "{Binding Nome}" FontSize="24" AbsoluteLayout.LayoutBounds="0.25, 0.25, 400, 40"/>
<Label Text = "{Binding CpfCnpj}" AbsoluteLayout.LayoutBounds="50, 35, 200, 25"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And my cs file:
private void OnItemAppearing(object sender, EventArgs e)
{
ViewCell theViewCell = (ViewCell)sender;
var item = theViewCell.BindingContext as Pessoa;
theViewCell.ContextActions.Clear();
if (item != null)
{
var pessoaVinculo = _pessoaVinculoRepository.Get(w => w.PessoaId == item.PessoaId && w.NegocioId == App.CurrentUser.NegocioId);
if (pessoaVinculo.NegocioAtivo)
{
var desativarAction = new MenuItem { Text = "Desativar", IsDestructive = true };
desativarAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
desativarAction.Clicked += DesativarParceiro;
var servicoAction = new MenuItem { Text = "Serviços" };
servicoAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
servicoAction.Clicked += CallServicos;
theViewCell.ContextActions.Add(desativarAction);
theViewCell.ContextActions.Add(servicoAction);
}
else
{
var aceitarVinculoAction = new MenuItem { Text = "Aceitar Vinculo" };
aceitarVinculoAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
aceitarVinculoAction.Clicked += AceitarConvite;
theViewCell.ContextActions.Add(aceitarVinculoAction);
}
}
}
When I try to access the MenuItem in Android it's work fine, but in iOS the MenuItem are not working.
How could i make this work?
This can be solved using two DataTemplates, one for each case, each one with the needed ContextActions, then use DataTemplateSelector to show the right DataTemplate.
Create your DataTemplateSelector and override the OnSelectTemplate method returning the right DataTemplate depending on your condition (pessoaVinculo.NegocioAtivo in your case).
Know more about DataTemplateSelector in
https://developer.xamarin.com/guides/xamarin-forms/templates/data-templates/selector
I'm making an XAML app and i'm having some issues binding my xaml file with its class .
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="App.TestXaml"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<ContentPage.Content>
<ListView x:Name="ListTest">
<Label FontSize="12" x:Name="test1"/>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Spacing="5" Orientation="Horizontal">
<Label FontSize="14" x:Name="test2"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
in my cs file testXaml.cs thats linked to this xaml :
test1.FontSize = 20 ;
// Works - it detects the test1 variable for that label.
In my listview however , when i try to access the label named test2 , it does not detect it in my cs file
test2.FontSize = 24 ;
// The class does not detect test2 (The name test2 does not exist in the current context)
Any idea how to fix this or set up a value for the list items from my cs file ?
You can't access the controls that are inside the itemtemplate by their name.
You have 2 options
Use a property in the binded item for the font size and bind it to the fontsize of the control. I think this is more clean solution.
Use triggers as described by #ed
But i would definetely go with Mvvm
If you need more programmatic decision here is another option.
Derive MyViewCell from ViewCell and your xml will look the same except MyViewCell and I added binding to show something. You will need to add local code reference to use MyViewCell in xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ButtonRendererDemo;assembly=ButtonRendererDemo"
x:Class="ButtonRendererDemo.ListCellAccessPage">
<ContentPage.Content>
<ListView x:Name="ListTest" HasUnevenRows="true">
<Label FontSize="12" x:Name="test1"/>
<ListView.ItemTemplate>
<DataTemplate>
<local:MyViewCell>
<StackLayout Spacing="5" Orientation="Horizontal">
<Label FontSize="14" x:Name="test2" Text="{Binding Name}"/>
</StackLayout>
</local:MyViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
</ContentPage>
Now here is the code behind
namespace ButtonRendererDemo
{
public partial class ListCellAccessPage : ContentPage
{
MyListItem[] listItems = new MyListItem[]
{
new MyListItem { Name= "1" },
new MyListItem{Name= "2" },
new MyListItem{Name= "3" },
new MyListItem{Name= "4" }
};
public ListCellAccessPage()
{
InitializeComponent();
test1.Text = "List";
ListTest.ItemsSource = listItems;
}
}
class MyListItem
{
public string Name { get; set; }
}
class MyViewCell : ViewCell
{
protected override void OnChildAdded(Element child)
{
base.OnChildAdded(child);
var label = child.FindByName<Label>("test2");
if (label != null)
{
label.PropertyChanged -= Label_PropertyChanged1;//unsubscribe in case of cell reuse
label.PropertyChanged += Label_PropertyChanged1;
}
private void Label_PropertyChanged1(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var label = sender as Label;
if ((label != null) && (e.PropertyName == "Text"))
{
if (label.Text == "3")
label.FontSize = 48;
else
label.FontSize = 14;//in case of cell reuse
}
}
}
}
So, it examines the content of your cell and if it is confirms certain condition (in this case name is 3) it sets the font. Here is the screenshot
I want add Text to ListView element when i press button:
private void button_Click(object sender, RoutedEventArgs e)
{
listView.Items.Add(textBox.Text);
}
It works but i got:
Element1
Element2
Element3
But i want to see something like:
[]Element1
[]Element2
Where [ ] is checkbox :)
My xaml:
<ListView x:Name="listView" HorizontalAlignment="Left" Height="406" Margin="10,224,0,0" VerticalAlignment="Top" Width="340" />
I don't see option CheckBoxes True/False in my xaml Properties
XAML
Modify the listView item template to add your custom layout.
Add a data binding to the set the text
<ListView x:Name="listView" HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="340">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<CheckBox/>
<Label Content="{Binding Text}"/>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Code Behind
declare this class somewhere
public class Row
{
private string text;
public Row (string text)
{
this.text = text;
}
public string Text
{
get { return text; }
set { text = value; }
}
}
Add this code to the constructor of the code associated with the xaml
ObservableCollection<Row> list = new ObservableCollection<Row>();
listView.ItemsSource = list;
How to add items/text to the listView
list.Add(new Row("Hello"));
list.Add(new Row("World"));
Hope this helps!
I am trying to display data from my SQL Server Compact 3.5. On my OnNavigateTo function, I have stated the codes but I am not sure why it is not able to load it. I am using Pivot App, Is it possible to use that to display my data? If yes, what have I done wrong. In the header=today is where I am displaying my data. Thanks.
Below are my codes
MainPage.xaml
<!--Pivot Control-->
<phone:Pivot Title="DAILY ROUTINE">
<!--Pivot item one-->
<phone:PivotItem Header="activity">
<!--Double line list with text wrapping-->
<phone:LongListSelector x:Name="MLongListSelector" Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionChanged="LongListSelector_SelectionChanged">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</phone:PivotItem>
<!--Pivot item two-->
<phone:PivotItem Header="today">
<!--Double line list with text wrapping-->
<phone:LongListSelector x:Name="MainLongListSelector" Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionChanged="LongListSelector_SelectionChanged">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding Id}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding Title}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</phone:PivotItem>
</phone:Pivot>
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using MyPhoneApp1.Resources;
namespace MyPhoneApp1
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
// Set the data context of the listbox control to the sample data
DataContext = App.ViewModel;
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
// Load data for the ViewModel Items
protected override void OnNavigatedTo(NavigationEventArgs e)
{
/*
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
* */
using (ToDoListContext c = new ToDoListContext(ToDoListContext.ConnectionString))
{
c.CreateIfNotExists();
c.LogDebug = true;
MainLongListSelector.ItemsSource = c.ToDoLists.ToList();
}
}
private void LongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var si = MLongListSelector.SelectedItem as MyPhoneApp1.ViewModels.ItemViewModel;
if (MLongListSelector.SelectedItem == null)
return;
if (si.LineOne.Equals("+ To Do List"))
NavigationService.Navigate(new Uri("/todolistPage.xaml", UriKind.Relative));
else if (si.LineOne.Equals("+ Reminder"))
NavigationService.Navigate(new Uri("/reminderPage.xaml", UriKind.Relative));
// Reset selected item to null (no selection)
MLongListSelector.SelectedItem = null;
}
}
}
I have debugged it and below is the SQL Statements
SELECT [t0].[Id], [t0].[Title]
FROM [ToDoLists] AS [t0]
I wouldn't suggest you directly set the ItemsSource property as you've already established a Binding in the XAML:
<phone:LongListSelector x:Name="MLongListSelector"
ItemsSource="{Binding Items}" >
Since the Binding Path is set to Items, changing the data of the list stored in Items will cause the UI to update automatically.
// get the list ...
var list = c.ToDoLists.ToList();
Debug.Assert(list != null);
// clear any existing items, which will in turn remove all items from the UI
App.ViewModel.Items.Clear();
// for each item in the list, add it to the existing bound Items list
foreach(var item in list) {
// you may need to transform the data here
// The item must be the right type ...
App.ViewModel.Items.Add(item);
}
As it looks like you're using the WP8 template, the ToDoLists property needs to return an enumerable list of ItemViewModels or the call to Add will fail. You could create new instances of an ItemViewModel if the types don't match (for example):
var itemViewModel = new ItemViewModel() {
LineOne = item.Text,
LineTwo = item.Description
};
App.ViewModel.Items.Add(itemViewModel);
The above code assumes then that a todo list item might look like this:
public class TodoItem {
public string Text { get; set; }
public string Description { get; set; }
}
I think this might be the problem you are binding the MainLongListSelector twice
in Xaml
ItemsSource="{Binding Items}"
and in c#
MainLongListSelector.ItemsSource = c.ToDoLists.ToList();
Looks like you need to remove the xaml binding