Datagrid not binding the image - datatable

I need to show an image in the datagrid, but its showing like below
System.windows.controls.Image
System.windows.controls.Image
The datatable i am adding the column with type as Image, and the row is contrcuted with reading the bytes[] and converting to an image then assigning to the datatable.
//Creating the column type
if (header.ColumnDescription == "ActiveStatus")
{
dc = new DataColumn(header.ColumnDescription, typeof(Image));
dt.Columns.Add(dc);
}
//Filling the data column
foreach (DataColumn col in dt.Columns)
{
dr[col] = GetRowItem(device, col.Caption);
}
dt.Rows.Add(dr);
//Logic for getting the image
Image img=new Image();
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri("pack://application:,,,/Resources/Images/cloud_logon_radio_btn_green.png");
logo.EndInit();
img.Source = logo
What is the issue?

Use AutoGeneratingColumn Event of the dataGrid to set the image .
Define Datatemplate in xaml
<DataTemplate x:Key="ActivaStatusColumnTemplate">
<Image DataContext="{Binding}" >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="red.png" />
<Style.Triggers>
<DataTrigger Value="On" Binding="{Binding}">
<Setter Property="Source" Value="green.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataTemplate>
//Code behind
private void dgView_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.Column.Header.ToString() == "ActiveStatus")
{
// Create a new template column.
MyDataGridTemplateColumn templateColumn = new MyDataGridTemplateColumn();
templateColumn.CellTemplate = (DataTemplate)Resources["ActivaStatusColumnTemplate"];
templateColumn.ColumnName = e.PropertyName; // so it knows from which column to get binding data
e.Column = templateColumn;
e.Column.Header = "ActiveStatus";
}
}
//Define the class to override the DataGridTemplateColumn
/// <summary>
/// Custom class derieved fromt the DataGridTemplateColumn to set the property name.
/// </summary>
public class MyDataGridTemplateColumn : DataGridTemplateColumn
{
public string ColumnName
{
get;
set;
}
protected override System.Windows.FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
// The DataGridTemplateColumn uses ContentPresenter with your DataTemplate.
ContentPresenter cp = (ContentPresenter)base.GenerateElement(cell, dataItem);
// Reset the Binding to the specific column. The default binding is to the DataRowView.
BindingOperations.SetBinding(cp, ContentPresenter.ContentProperty, new Binding(this.ColumnName));
return cp;
}
}
refer
http://social.msdn.microsoft.com/Forums/en/wpf/thread/8b2e94b7-3c44-4642-8acc-851de5285062

if you want to show image into browser you have to generate a url .
you cannot show image directly from binary .
you can try using a handler file (.ashx) put the code form your page_load in that file
and in you handler code like
public void ProcessRequest (HttpContext context) {
//Get the picture id by url
//Query here
byte[] picture = queryoutput;
Response.ContentType = "images/jpeg";
Response.BinaryWrite(picture);
}
public bool IsReusable {
get {
return false;
}
}

Related

[UWP How to get control of a UserControl placed inside a ListView without altering the listview binding source?

I have placed a UserControl inside a ListView.
How do I get the control of this UserControl in the view.
If I place it inside a ListView, I am unable to access it in the view. I also do not wish to make any changes to the listView binding source.
Its name isn't accessible directly in the view.
I am able to access the events but not Properties(x:Name , Visibility etc..).
You can use VisualTreeHelper class to get your UserControl .
Get each ListViewItem by calling the ListView's ContainerFromItem or ContainerFromIndex.
Create a recursive function to find the DependencyObjects that are in each ListViewItem as a UserControl.
I made a simple to show how it works. You can refer to the following code.
MainPage.xaml
<Grid>
<ListView x:Name="MyListView" Margin="0,0,0,109">
<ListView.ItemTemplate>
<DataTemplate x:DataType="x:String">
<Grid>
<local:MyUserControl1></local:MyUserControl1>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="Button" Margin="682,943,0,0" VerticalAlignment="Top" Click="Button_Click"/>
</Grid>
MainPage.cs
public List<string> ItemsSourceList { get; set; }
public MainPage()
{
this.InitializeComponent();
ItemsSourceList = new List<string>();
ItemsSourceList.Add("1");
ItemsSourceList.Add("2");
ItemsSourceList.Add("3");
ItemsSourceList.Add("4");
ItemsSourceList.Add("5");
MyListView.ItemsSource = ItemsSourceList;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
foreach (var strItem in ItemsSourceList)
{
// get every listview item first
ListViewItem item = MyListView.ContainerFromItem(strItem) as ListViewItem;
// the DependencyObject is the UserControl that you want to get
DependencyObject myUserControl = FindChild(item);
}
}
public DependencyObject FindChild(DependencyObject parant)
{
int count = VisualTreeHelper.GetChildrenCount(parant);
for (int i = 0; i < count; i++)
{
var MyChild = VisualTreeHelper.GetChild(parant, i);
if (MyChild is MyUserControl1)
{
//Here can get the MyUserControl1.
MyUserControl1 myUserControl = (MyUserControl1)MyChild;
myUserControl.Foreground = new SolidColorBrush(Colors.Red);
return myUserControl;
}
else
{
var res = FindChild(MyChild);
return res;
}
}
return null;
}

Create bindable properties for Treeview in Xamarin Forms

I needed to use a Treeview in my xamarin forms application, however the only existing TreeView on the net are not free (Syncfusion and Telerik).
So I found this very interesting project : https://github.com/AdaptSolutions/Xamarin.Forms-TreeView
the only problem that I found is that the ItemSource and SelectedItem properties are not bindable and therefor I can't use it on an MVVM Pattern. Which brings us to my question, How can I make them bindable.
I tried to follow this documentation : https://learn.microsoft.com/en-us/xamarin/xamarin-forms/xaml/bindable-properties
but still nothing. Can anyone help me with that please ? Thank you
UPDATE :
this is the TreeView class :
public class TreeView : ScrollView
{
#region Fields
private readonly StackLayout _StackLayout = new StackLayout { Orientation = StackOrientation.Vertical };
//TODO: This initialises the list, but there is nothing listening to INotifyCollectionChanged so no nodes will get rendered
private IList<TreeViewNode> _RootNodes = new ObservableCollection<TreeViewNode>();
private TreeViewNode _SelectedItem;
#endregion
#region Public Properties
public TreeViewNode SelectedItem
{
get => _SelectedItem;
set
{
if (_SelectedItem == value)
{
return;
}
if (_SelectedItem != null)
{
_SelectedItem.IsSelected = false;
}
_SelectedItem = value;
SelectedItemChanged?.Invoke(this, new EventArgs());
}
}
public IList<TreeViewNode> RootNodes
{
get => _RootNodes;
set
{
_RootNodes = value;
if (value is INotifyCollectionChanged notifyCollectionChanged)
{
notifyCollectionChanged.CollectionChanged += (s, e) =>
{
RenderNodes(_RootNodes, _StackLayout, e, null);
};
}
RenderNodes(_RootNodes, _StackLayout, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset), null);
}
}
#endregion
#region Constructor
public TreeView()
{
Content = _StackLayout;
}
#endregion
#region Private Static Methods
private static void AddItems(IEnumerable<TreeViewNode> childTreeViewItems, StackLayout parent, TreeViewNode parentTreeViewItem)
{
foreach (var childTreeNode in childTreeViewItems)
{
if (!parent.Children.Contains(childTreeNode))
{
parent.Children.Add(childTreeNode);
}
childTreeNode.ParentTreeViewItem = parentTreeViewItem;
}
}
#endregion
#region Internal Static Methods
internal static void RenderNodes(IEnumerable<TreeViewNode> childTreeViewItems, StackLayout parent, NotifyCollectionChangedEventArgs e, TreeViewNode parentTreeViewItem)
{
if (e.Action != NotifyCollectionChangedAction.Add)
{
AddItems(childTreeViewItems, parent, parentTreeViewItem);
}
else
{
AddItems(e.NewItems.Cast<TreeViewNode>(), parent, parentTreeViewItem);
}
}
#endregion
}
so what Im trying to do here is making RootNodes bindable as well as SelectedItem afterwards.
What I did is simply adding this, thinking it should work but obviously it does not :
public static readonly BindableProperty RootNodesProperty =
BindableProperty.Create(nameof(RootNodes), typeof(IList<TreeViewNode>), typeof(TreeView));
public IList<TreeViewNode> RootNodes
{
get => (IList<TreeViewNode>)GetValue(RootNodesProperty);
set
{
SetValue(RootNodesProperty, value);
_RootNodes = value;
if (value is INotifyCollectionChanged notifyCollectionChanged)
{
notifyCollectionChanged.CollectionChanged += (s, e) =>
{
RenderNodes(_RootNodes, _StackLayout, e, null);
};
}
RenderNodes(_RootNodes, _StackLayout, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset), null);
}
}
UPDATE 2 :
Here is what it looks like
Hope this helps
It seems you will not need to create custom ItemSource and SelectedItem in ScrollView, because Xamarin Foms has Bindable Layouts that contains ItemsSource and ItemTemplateSelector .
Bindable layouts enable any layout class that derives from the Layout class to generate its content by binding to a collection of items, with the option to set the appearance of each item with a DataTemplate. Bindable layouts are provided by the BindableLayout class, which exposes the following attached properties:
ItemsSource – specifies the collection of IEnumerable items to be displayed by the layout.
ItemTemplate – specifies the DataTemplate to apply to each item in the collection of items displayed by the layout.
ItemTemplateSelector – specifies the DataTemplateSelector that will be used to choose a DataTemplate for an item at runtime.
If you need to use ScrollView, sample code as follows:
<ScrollView>
<StackLayout BindableLayout.ItemsSource="{Binding User.TopFollowers}"
Orientation="Horizontal"
...>
<BindableLayout.ItemTemplate>
<DataTemplate>
<controls:CircleImage Source="{Binding}"
Aspect="AspectFill"
WidthRequest="44"
HeightRequest="44"
... />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ScrollView>

How can I set up different footers for TableSections when using a Custom TableView Renderer

I am using a renderer to allow me to set a custom footer in my TableView. The renderer works but I would like to have the capability to set up different footers for the different table sections. For example one footer for table section 0 and another for table section 1, all the way up to table section 5.
Here's the XAML that I am using:
<!-- <local:ExtFooterTableView x:Name="tableView" Intent="Settings" HasUnevenRows="True">-->
<TableView x:Name="tableView" Intent="Settings" HasUnevenRows="True">
<TableSection Title="Cards1">
<ViewCell Height="50">
<Label Text="Hello1" />
</ViewCell>
<ViewCell Height="50">
<Label Text="Hello2" />
</ViewCell>
</TableSection>
<TableSection Title="Cards2">
<TextCell Height="50" Text="Hello"></TextCell>
</TableSection>
</TableSection>
<!-- </local:ExtFooterTableView>-->
</TableView>
and here is the C# class and renderer:
public class ExtFooterTableView : TableView
{
public ExtFooterTableView()
{
}
}
and:
using System;
using Japanese;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtFooterTableView), typeof(Japanese.iOS.ExtFooterTableViewRenderer))]
namespace Japanese.iOS
{
public class ExtFooterTableViewRenderer : TableViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
{
base.OnElementChanged(e);
if (Control == null)
return;
var tableView = Control as UITableView;
var formsTableView = Element as TableView;
tableView.WeakDelegate = new CustomFooterTableViewModelRenderer(formsTableView);
}
private class CustomFooterTableViewModelRenderer : TableViewModelRenderer
{
public CustomFooterTableViewModelRenderer(TableView model) : base(model)
{
}
public override UIView GetViewForFooter(UITableView tableView, nint section)
{
Debug.WriteLine("xx");
if (section == 0)
{
return new UILabel()
{
// Text = TitleForFooter(tableView, section), // or use some other text here
Text = "abc",
TextAlignment = UITextAlignment.Left
// TextAlignment = NSTextAlignment.NSTextAlignmentJustified
};
}
else
{
return new UILabel()
{
// Text = TitleForFooter(tableView, section), // or use some other text here
Text = "def",
TextAlignment = UITextAlignment.Left
// TextAlignment = NSTextAlignment.NSTextAlignmentJustified
};
}
}
}
}
}
The code works but I would like to find out how I can set up a different footer text for different sections in the XAML. Something like this:
From what I see it looks like the code is partly there TitleForFooter(tableView, section) but I am not sure how to use it and how I could set it up. Note that I am not really looking for a view model solution. I would be happy to be simply able to specify the section footer text as part of the TableView XAML.
I'd appreciate if anyone could give me some advice on this.
First of all, in order to be able to specify the section footer text in XAML - simplest option would be to create a bindable property in TableSection. But as TableSection is sealed, we can't derive it to define our custom bindable properties.
So, the next option is to create a attached bindable property.
public class Ex
{
public static readonly BindableProperty FooterTextProperty =
BindableProperty.CreateAttached("FooterText", typeof(string), typeof(Ex), defaultValue: default(string));
public static string GetFooterText(BindableObject view)
{
return (string)view.GetValue(FooterTextProperty);
}
public static void SetFooterText(BindableObject view, string value)
{
view.SetValue(FooterTextProperty, value);
}
}
Next step would be to update renderer to retrieve this value for every section:
private class CustomFooterTableViewModelRenderer : TableViewModelRenderer
{
public CustomFooterTableViewModelRenderer(TableView model) : base(model)
{
}
public override UIView GetViewForFooter(UITableView tableView, nint section)
{
return new UILabel()
{
Text = TitleForFooter(tableView, section), // or use some other text here
Font = UIFont.SystemFontOfSize(14),
ShadowColor = Color.White.ToUIColor(),
ShadowOffset = new CoreGraphics.CGSize(0, 1),
TextColor = Color.DarkGray.ToUIColor(),
BackgroundColor = Color.Transparent.ToUIColor(),
Opaque = false,
TextAlignment = UITextAlignment.Center
};
}
//Retrieves the footer text for corresponding section through the attached property
public override string TitleForFooter(UITableView tableView, nint section)
{
var tblSection = View.Root[(int)section];
return Ex.GetFooterText(tblSection);
}
}
Sample Usage
<local:ExtFooterTableView x:Name="tableView" Intent="Settings" HasUnevenRows="True">
<TableSection Title="Cards1" local:Ex.FooterText="Sample description">
<ViewCell Height="50">
<Label Margin="20,0,20,0" Text="Hello1" />
</ViewCell>
<ViewCell Height="50">
<Label Margin="20,0,20,0" Text="Hello2" />
</ViewCell>
</TableSection>
<TableSection Title="Cards2" local:Ex.FooterText="Disclaimer note">
<TextCell Height="50" Text="Hello"></TextCell>
</TableSection>
</local:ExtFooterTableView>
It is very simple. you need to add the bindable property for pass value from XAML to CustomRenderer in CustomControl like this:
Customer TableView
public class ExtFooterTableView : TableView
{
public ExtFooterTableView()
{
}
}
Xaml control code
<local:ExtFooterTableView x:Name="tableView" Intent="Settings" HasUnevenRows="True">
Renderer class
using System;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using yournamespace;
using System.ComponentModel;
[assembly: ExportRenderer(typeof(ExtFooterTableView), typeof(FooterTableViewRenderer))]
namespace yournamespace
{
public class FooterTableViewRenderer : TableViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
{
base.OnElementChanged(e);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var view = (ExtFooterTableView)Element;
if (e.PropertyName == ExtFooterTableView.IntentProperty.PropertyName)
{
string intent = view.Intent;
// Do your stuff for intent property
}
if (e.PropertyName == ExtFooterTableView.HasUnevenRowsProperty.PropertyName)
{
bool hasUnevenRows = view.HasUnevenRows;
// Do yout stuff for HasUnevenRow
}
}
}
}

How can I make a > in a cell with Xamarin.Forms?

I have an application where I can change the order and the way cards appear. For anyone who has iOS I need something very similar to the way the Settings > Contacts > Sort Order page works.
This shows two rows. One with First, Last and the other with Last, First. When a user clicks on a row it acts like a radio button and a tick mark appears at the end of the row.
I would like to try and implement this functionality but I am not sure where to start. Should I do this with a ViewCell or a TextCell and how does anyone have any ideas as to how it is implemented this
. 

EDIT 1: Simplified property changed logic in iOS renderer; now there are no references or handlers to cleanup.
In extension to #hankide's answer:
You can create a bindable property IsChecked while extending a TextCell or ViewCell and bind your VM state to it.
public class MyTextCell : TextCell
{
public static readonly BindableProperty IsCheckedProperty =
BindableProperty.Create(
"IsChecked", typeof(bool), typeof(MyTextCell),
defaultValue: false);
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
}
Next step would be to create renderer that listens to this property and shows a check-mark at iOS level.
[assembly: ExportRenderer(typeof(MyTextCell), typeof(SampleApp.iOS.MyTextCellRenderer))]
namespace SampleApp.iOS
{
public class MyTextCellRenderer : TextCellRenderer
{
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var nativeCell = base.GetCell(item, reusableCell, tv);
var formsCell = item as MyTextCell;
SetCheckmark(nativeCell, formsCell);
return nativeCell;
}
protected override void HandlePropertyChanged(object sender, PropertyChangedEventArgs args)
{
base.HandlePropertyChanged(sender, args);
System.Diagnostics.Debug.WriteLine($"HandlePropertyChanged {args.PropertyName}");
if (args.PropertyName == MyTextCell.IsCheckedProperty.PropertyName)
{
var nativeCell = sender as CellTableViewCell;
if (nativeCell?.Element is MyTextCell formsCell)
SetCheckmark(nativeCell, formsCell);
}
}
void SetCheckmark(UITableViewCell nativeCell, MyTextCell formsCell)
{
if (formsCell.IsChecked)
nativeCell.Accessory = UITableViewCellAccessory.Checkmark;
else
nativeCell.Accessory = UITableViewCellAccessory.None;
}
}
}
Sample usage 1
And, sample usage would like:
<TableView Intent="Settings">
<TableSection Title="Sort Order">
<local:MyTextCell Text="First Last" IsChecked="false" />
<local:MyTextCell Text="Last, First" IsChecked="true" />
</TableSection>
</TableView>
Sample usage 2
You can also listen to Tapped event to ensure IsChecked property works as expected.
For example, you bind this property to ViewModel:
<TableView Intent="Settings">
<TableSection Title="Sort Order">
<local:MyTextCell Tapped="Handle_Tapped" Text="{Binding [0].Name}" IsChecked="{Binding [0].IsSelected}" />
<local:MyTextCell Tapped="Handle_Tapped" Text="{Binding [1].Name}" IsChecked="{Binding [1].IsSelected}" />
</TableSection>
</TableView>
and handle tap event:
public SettingViewModel[] Settings = new []{
new SettingViewModel { Name = "First Last", IsSelected = false },
new SettingViewModel { Name = "Last First", IsSelected = true },
};
void Handle_Tapped(object sender, System.EventArgs e)
{
var cell = sender as TextCell;
if (cell == null)
return;
var selected = cell.Text;
foreach(var setting in Settings)
{
if (setting.Name == selected)
setting.IsSelected = true;
else
setting.IsSelected = false;
}
}
The sort order settings page you described is implemented using the UIKit's UITableView. In Xamarin.Forms, you can utilize the TableView control to get the same result.
As you will quickly notice, there's no way to set the checkmark icon with Xamarin.Forms so you'll probably need to create a custom cell, that has the text on the left and the checkmark image on the right.
If you really want to do everything by the book, you should probably create a custom renderer that allows you to set the Accessory property of the current ViewCell. However, this will get a bit complex for such a small feature.

WP7 - Update ListPicker items asynchronous

In this case isn't supposed that I can see the values from list in ListPicker?
xaml
<toolkit:ListPicker
x:Name="lpkBoards"
ItemsSource="{Binding AllBoards}"
DisplayMemberPath="Name" >
</toolkit:ListPicker>
xaml.cs
public SettingsPage()
{
InitializeComponent();
// Set the page DataContext property to the ViewModel.
this.DataContext = App.ViewModel;
...
boardsTask.ContinueWith(
(call) =>
{
App.ViewModel.AllBoards = call.Result.ToList();
}
);
ViewModel
// All to-do items.
private List<Board> _allBoards;
public List<Board> AllBoards
{
get { return _allBoards; }
set
{
_allBoards = value;
NotifyPropertyChanged("AllBoards");
}
}
You need to change the List<Board> to ObservalbeCollection<Board> if you are trying to bind it to a UI element and want it to work.

Resources