display a timer using progressBar xamarin forms - xaml

how to add a nice timer
xaml :
<ProgressBar x:Name="progressBar" Grid.Row="2" Grid.ColumnSpan="5"
IsVisible="true"
Progress="0.0"
WidthRequest="300"
HeightRequest="20"
VerticalOptions="Center"
HorizontalOptions="Center">
</ProgressBar>
behind code:
progressBar.Progress = 0;
await progressBar.ProgressTo(1.0, 90000, Easing.Linear);

You can use a timer to increment the ProgressBar:
var updateRate = 1000 / 30f; // 30Hz
double step = updateRate / (2 * 30 * 1000f);
Device.StartTimer(TimeSpan.FromMilliseconds(updateRate), () =>
{
if (progressBar.Progress < 100)
{
Device.BeginInvokeOnMainThread(() => progressBar.Progress += step );
return true;
}
return false;
});
Then you can use an IValueConverter to convert the progress to a minute:second style format:
public class CountDownConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double time = 0;
double.TryParse(parameter.ToString(), out var totalTime);
double.TryParse(value.ToString(), out var progress);
time = progress <= double.Epsilon ? totalTime : (totalTime - (totalTime * progress));
var timeSpan = TimeSpan.FromMilliseconds(time);
return $"{timeSpan.Minutes:00;00}:{timeSpan.Seconds:00;00}";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Tying it together with XAML:
<Label
BindingContext="{x:Reference progressBar}"
Text = "{Binding Progress, StringFormat='{0:P0}'}"
HorizontalOptions ="Center"
FontSize="20"
FontFamily = "Helvetica Neue"
TextColor ="Red" />
<ProgressBar x:Name="progressBar"
IsVisible="true"
Progress="0.0"
WidthRequest="300"
HorizontalOptions="Center">
</ProgressBar>
<Label Text="{Binding Source={x:Reference progressBar},
Path=Progress,
Converter={StaticResource countDownTime},
ConverterParameter=120000}}"
HorizontalOptions ="Center"
FontSize="20"
FontFamily = "Helvetica Neue"
TextColor = "Red" />
Output:
Update:
You have to define a ResourceDictionary to have an instance of the CountDownConverter class created and named so you can reference it in XAML:
<ContentPage.Resources>
<ResourceDictionary>
<tools:CountDownConverter x:Key="countDownTime"/>
</ResourceDictionary>
</ContentPage.Resources>
And the tools: namespace reference is based upon the C# namespace and assembly that contains the CountDownConverter. I have a bunch of these IValueConverter classes in a separate library and thus my xmlns:tools looks like:
xmlns:tools="clr-namespace:Converters;assembly=Converters"
re: Resource Dictionaries

Related

Retrieving ItemsSource from a BindableLayout

I have a FlexLayout with a BindableLayout.
<FlexLayout BindableLayout.ItemsSource="{Binding CardItems}" x:Name="SourceLayout" Background="green"
Direction="Row" Wrap="Wrap">
<BindableLayout.ItemTemplate>
<DataTemplate>
<ContentView>
<Frame CornerRadius="20" Padding="0" WidthRequest="150" Margin="10"
HeightRequest="150"
BackgroundColor="{Binding .,
Converter={StaticResource AlternateColorConverter},
ConverterParameter={x:Reference SourceLayout}}">
<StackLayout>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.CardItemNavCommand, Source={x:Reference SourceLayout}}"
CommandParameter="{Binding NavTarget}"/>
</StackLayout.GestureRecognizers>
<Label Text="{Binding Text}" TextColor="Black" FontSize="20" VerticalOptions="FillAndExpand"/>
<Label Text="{Binding Text}" TextColor="Black" FontSize="20" VerticalOptions="FillAndExpand"/>
</StackLayout>
</Frame>
</ContentView>
</DataTemplate>
</BindableLayout.ItemTemplate>
</FlexLayout>
Is it possible to get the index of the current item inside the converter so I can change the color accordingly? I know this can be achieved with a ListView because I can access the items source property but I can't access the resource from the BindableLayout.
Is it possible to get the index of the current item inside the converter so I can change the color accordingly
BindableLayout is a static class, so we cannot get it from the layout to get the itemsSource.
For this function ,try to create an 'Identifier' property in the model class and set binding for the backgroundColor. Then get the value in the converter class to obtain the index of the current item from the data collection. Sepcify the background color according to the index.
Check the code:
App.xaml.cs
public partial class App : Application
{
public static TestPageViewModel viewModel;
public App()
{
InitializeComponent();
viewModel = new TestPageViewModel();
MainPage = new NavigationPage(new TestPage());
}
}
Page.xaml
<StackLayout BindableLayout.ItemsSource="{Binding DataCollection}" ...>
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid Padding="0,2,3,0" BackgroundColor="{Binding Identifier, Converter={StaticResource _converter}}">
...
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
Page.xaml.cs
public partial class TestPage : ContentPage
{
public TestPage()
{
InitializeComponent();
BindingContext = App.viewModel;
}
}
Model class
public class TestPageModel
{
public string Content { get; set; }
public string Identifier { get; set; }
}
ValueConverter class
public class TestPageValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var index = GetValue(value);
switch (index)
{
case 1:
return Color.LightBlue;
break;
case 2:
return Color.LightPink;
break;
case 3:
return Color.LightYellow;
break;
default:
break;
}
return Color.White;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return -1;
}
double GetValue(object value)
{
var viewModel = App.viewModel;
foreach (var item in viewModel.DataCollection)
{
if (item.Identifier == (string)value)
{
return viewModel.DataCollection.IndexOf(item) + 1;
}
}
return -1;
}
}

Change color in listview item and remove item UWP

I would remove an item with button inside listview item and change color of ellipse with another button in listview item.
The class product code:
class Product
{
public string Name { get; set; }
public double Price { get; set; }
}
The xaml mainpage code:
<Page
x:Class="ListViewTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ListViewTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Loaded="Page_Loaded">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView x:Name="ListViewProducts"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
FontSize="18"
BorderThickness="0"
Width="600"
Height="800"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ItemsSource="{Binding LineItems}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10">
<Grid HorizontalAlignment="Left" VerticalAlignment="Center" Margin="5,0,0,0">
<Ellipse x:Name="EllipseColor" HorizontalAlignment="Left" Height="20" Stroke="Black" VerticalAlignment="Top" Width="20" StrokeThickness="1"/>
</Grid>
<TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
<TextBlock Text="{Binding Price}" Margin="5,0,0,0"/>
<Button x:Name="btnRemove" Click="btnRemove_Click" Height="20" Width="60" Margin="5"/>
<Button x:Name="btnChangeColor" Click="btnChangeColor_Click" Height="20" Width="60" Margin="5"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
The code behind of mainpage:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
ObservableCollection<Product> _listProduct = new ObservableCollection<Product>();
_listProduct = new ObservableCollection<Product>
{
new Product
{
Name = "Phone",
Price = 100
},
new Product
{
Name = "TV",
Price = 120
},
new Product
{
Name = "Computer",
Price = 80
},
new Product
{
Name = "Laptop",
Price = 250
},
new Product
{
Name = "Tablet",
Price = 150
},
new Product
{
Name = "Monitor",
Price = 200
},
};
ListViewProducts.ItemsSource = _listProduct;
}
private void btnRemove_Click(object sender, RoutedEventArgs e)
{
// Code to remove item
}
private void btnChangeColor_Click(object sender, RoutedEventArgs e)
{
// Code to color EllipseColor
}
}
With btnRemove i would delete listview item and with btnChangeColor i would color red the fill of EllipseColor, in btnChangeColor_Click i would the index of item.
Thanks in advance.
It looks to me like you've got several issues. First off is that you're setting your ListView source via binding to an apparently non-existent collection, as well as setting it in C#. You should move it to using a proper binding. For example, in MainPage.xaml.cs:
private ObservableCollection<Product> _products = new ObservableCollection<Product>();
public ObservableCollection<Product> Products { get => _products; set => _products = value; }
And then bind to it:
<ListView ItemsSource={x:Bind Products, Mode=OneWay} />
Then, in btnRemove_Click, you can just remove the item from the collection:
var product = (sender as Button).DataContext as Product;
Products.Remove(product);
As for coloring the Ellipse, you shouldn't really do that in C#. Instead, you should have a Status property on your Product class, and then change that property.
First off, you'll need to make sure your property changes fire notifications.
public class Product : INotifyPropertyChanged
{
private string _status;
public string Status
{
get => _status;
set
{
_status = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Status)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Then change the property.
var product = (sender as Button).DataContext as Product;
product.Status = "invalid";
Then in your XAML, use a binding converter to change the Ellipse's Fill property based on the status. E.g.
using System;
using Windows.UI;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
public class StatusConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language) =>
new SolidColorBrush(value.ToString() == "invalid" ? Colors.Red : Colors.Gray);
public object ConvertBack(object value, Type targetType, object parameter, string language) =>
throw new NotImplementedException();
}
You'll then need to add the converter to your resources.
<Page...>
<Page.Resources>
<locationofyourconverter:StatusConverter x:Key="StatusConverter" />
</Page.Resources>
...
<Ellipse Fill={Binding Status, Mode=OneWay, Converter={StaticResource StatusConverter}} />

Passing additional arguments to user control inside the data template

This is the xaml code what i am using
<GridView
Grid.Row="0"
x:Name="RootGrid"
SelectionMode="None"
IsItemClickEnabled="True"
ItemsSource="{Binding RootListSource}">
<GridView.ItemTemplate>
<DataTemplate>
<UserControl:TreeInfoControl/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
In this my user control, it contain another GridView that holds a different IEnumerable collection. What i am trying to achieve is i need to pass this collection through code. I tried this by adding a dependency property to the treecontrol but it is not working. So i am looking for a solution that enable passing the collection through xaml (somehow through the user control). I know it is possible to add that collection to my existing collection and bind that one. But for now i can't use that method.
Here's how you do it.
Start with your App.xaml so we can reuse the demo template
<Application.Resources>
<DataTemplate x:Key="MyContentControl">
<Grid Height="100" Width="100" Background="Maroon">
<TextBlock Text="{Binding FallbackValue=0}" Foreground="White" FontSize="40" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>
</DataTemplate>
</Application.Resources>
Then we can define your user control
<d:UserControl.DataContext>
<local:MyControlViewModel Number="-1" Letter="~K" />
</d:UserControl.DataContext>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left">
<ContentControl Content="{Binding Number}"
ContentTemplate="{StaticResource MyContentControl}" />
<ListView ItemsSource="{Binding Letters}" IsHitTestVisible="False"
ItemTemplate="{StaticResource MyContentControl}"
SelectedItem="{Binding Letter, Mode=TwoWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListView>
</StackPanel>
And then we can define your MainPage.xaml
<Page.DataContext>
<local:MainPageViewModel Letter="C" />
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListView x:Name="MyList" ItemsSource="{Binding Letters}"
ItemTemplate="{StaticResource MyContentControl}"
SelectedItem="{Binding Letter, Mode=TwoWay}" />
<ListView Grid.Column="1" ItemsSource="{Binding Numbers}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<local:MyControlViewModel
x:Key="MyDataContext" Number="{Binding}"
Letters="{Binding ItemsSource, ElementName=MyList}"
Letter="{Binding SelectedItem, ElementName=MyList}" />
</StackPanel.Resources>
<local:MyControl DataContext="{StaticResource MyDataContext}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Nothing special yet, right? Well, not so fast. We're creating the viewmodel for the user control , setting the properties of the view model from the surrounding scope, then passing it in to the DataContext of the user control explicitly. Cool, huh? Simple enough, if you think about it. Want to set those properties inside the tag? Sure you do. But you can't. The order of operation would be all wrong. You'll just have to trust me.
Now, there's ZERO code behind for your user control. But the view model looks like this:
public class MyControlViewModel : BindableBase
{
public int Number
{
get { return (int)GetValue(NumberProperty); }
set
{
SetValue(NumberProperty, value);
base.RaisePropertyChanged();
}
}
public static readonly DependencyProperty NumberProperty =
DependencyProperty.Register("Number", typeof(int), typeof(MyControlViewModel),
new PropertyMetadata(0, (s, e) => { }));
public string Letter
{
get { return (string)GetValue(LetterProperty); }
set
{
SetValue(LetterProperty, value);
base.RaisePropertyChanged();
}
}
public static readonly DependencyProperty LetterProperty =
DependencyProperty.Register("Letter", typeof(string), typeof(MyControlViewModel),
new PropertyMetadata("Z", (s, e) => { }));
public ObservableCollection<string> Letters
{
get { return (ObservableCollection<string>)GetValue(LettersProperty); }
set
{
SetValue(LettersProperty, value);
base.RaisePropertyChanged();
}
}
public static readonly DependencyProperty LettersProperty =
DependencyProperty.Register("Letters", typeof(ObservableCollection<string>),
typeof(MyControlViewModel),
new PropertyMetadata(new ObservableCollection<string>(new[] { "~W", "~X", "~Y", "~Z" }), (s, e) => { }));
}
All the properties are dependency properties. I hope you noticed. I didn't just do that because I like to type. Though I do like to type. Fact is, I did that because in order to have internal binding you must use a dependency property - and a dependency property that raises property changed! That last part isn't trivial. But does it have to be in a view model? No. But I like it that way.
You might reference this: http://blog.jerrynixon.com/2013/07/solved-two-way-binding-inside-user.html
There's also no code behind for your MainPage. But the view model looks like this:
public class MainPageViewModel : BindableBase
{
public MainPageViewModel()
{
this._Letters = new ObservableCollection<string>(new[] { "A", "B", "C", "D" });
this._Numbers = new ObservableCollection<int>(new[] { 1, 2, 3, 4 });
}
public string Letter
{
get { return (string)GetValue(LetterProperty); }
set
{
SetValue(LetterProperty, value);
base.RaisePropertyChanged();
}
}
public static readonly DependencyProperty LetterProperty =
DependencyProperty.Register("Letter", typeof(string), typeof(MyControlViewModel),
new PropertyMetadata("Z", (s, e) => { }));
ObservableCollection<string> _Letters = new ObservableCollection<string>();
public ObservableCollection<string> Letters { get { return _Letters; } }
ObservableCollection<int> _Numbers = new ObservableCollection<int>();
public ObservableCollection<int> Numbers { get { return _Numbers; } }
}
The bindable base is standard, here's the code for it:
public abstract class BindableBase : DependencyObject, System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] String propertyName = null)
{
if (!object.Equals(storage, value))
{
storage = value;
if (PropertyChanged != null)
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
protected void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] String propertyName = null)
{
if (PropertyChanged != null)
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
When it's all done, you should get exactly what you want. Something like this:
Not to over-simplify things. But, it's that easy.
Look, getting your head wrapped around XAML is not always easy when you start to nest contexts. I don't blame you for not getting it on first run. But I hope this helps you get started. Keep pushing
Best of luck!

Silverlight DataGridRow Background color change based on a column value and bind from the datagrid itemsource

I am trying to color the row based on a column value and may be other calculations in the value converter, but as long as I set the background value to any binding or anything but the hardcoded color Value="Red" in the setter, it throws a XAML parsing error. I am implementing like this:
<sdk:DataGrid ItemsSource="{Binding
EmailJobs}"
AutoGenerateColumns="False"
Height="Auto"
HorizontalAlignment="Center"
Name="dgEmailJObs"
VerticalAlignment="Top"
Width="Auto" Grid.Row="2">
<sdk:DataGrid.RowStyle>
<Style TargetType="sdk:DataGridRow">
<Style.Setters>
<Setter Property="Background"
Value="{Binding Path=Status,
Converter={StaticResource
valueConverter}}"/>
</Style.Setters>
</Style>
</sdk:DataGrid.RowStyle>
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn
CanUserReorder="False"
CanUserResize="False"
CanUserSort="True" Header="Customer"
Width="Auto" Binding="{Binding
Customer}" />
<sdk:DataGridTextColumn
CanUserReorder="False"
CanUserResize="False"
CanUserSort="True" Header="Program"
Width="Auto" Binding="{Binding
Program}" />
<sdk:DataGridTextColumn
CanUserReorder="False"
CanUserResize="False"
CanUserSort="True"
Header="Application" Width="Auto"
Binding="{Binding Application}"/>
<sdk:DataGridTextColumn
CanUserReorder="True"
CanUserResize="False"
CanUserSort="True" Header="Status"
Width="Auto" Binding="{Binding
Status}"></sdk:DataGridTextColumn>
<sdk:DataGridTextColumn
CanUserReorder="False"
CanUserResize="False"
CanUserSort="True" Header="Last
Created By" Width="Auto"
Binding="{Binding LastChangedBy}"/>
<sdk:DataGridTextColumn
CanUserReorder="False"
CanUserResize="False"
CanUserSort="True" Header="Last
Created On" Width="Auto"
Binding="{Binding
LastChangedOn,StringFormat='MM/DD/YYYY
hh:mm tt'}" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
I am using MVVM and dont wanna use the triggering event. All I want is to simply supply the fourth column value to the converter, but it blows up, should be pretty simple jsut lack of XAML binding knowledge :( any help
I think I see... Silverlight 4 doesn't allow (anymore) bindings into Setters.
However there are 2 simple solutions to solve your issue :
You can remove the <sdk:DataGrid.RowStyle> and its content and replace it by RowStyle="{Binding Path=Status, Converter={StaticResource valueConverter}}" as a property of your datagrid (example below)
<sdk:DataGrid Grid.Column="1" ItemsSource="{Binding EmailJobs}" RowStyle="{Binding Path=Status, Converter={StaticResource valueConverter}}" AutoGenerateColumns="False" HorizontalAlignment="Center" Name="dgEmailJObs" Width="Auto" Margin="0,0,0,87" LoadingRow="dgEmailJObs_LoadingRow">
Or, you can manage it in the code behind after triggering the event LoadingRow:
void dgEmailJObs_LoadingRow(object sender, DataGridRowEventArgs e)
{
myClass c = e.Row.DataContext as myClass;
if (c != null)
{
if (c.Status == "Stopped")
{
e.Row.Background = new SolidColorBrush(Colors.Red);
}
else
{
e.Row.Background = new SolidColorBrush(Colors.Green);
}
}
}
Hope that helps ;)
private void grdPendingRequest_LoadingRow(object sender, DataGridRowEventArgs e)
{
string changedColPath = string.Empty;
dynamic itemData = (dynamic)e.Row.DataContext;
if (itemData != null)
changedColPath = itemData.Changed_Field;
if (changedColPath != string.Empty)
{
string colPath;
System.Windows.Data.Binding binding;
string[] ChangedColNameList = null;
foreach (DataGridColumn col in grdPendingRequest.Columns)
{
if (col is DataGridBoundColumn)
{
binding = (col as DataGridBoundColumn).Binding;
colPath = binding.Path.Path;
ChangedColNameList = changedColPath.Split(';');
if (ChangedColNameList.Contains(colPath))
{
FrameworkElement felt = col.GetCellContent(e.Row);
FrameworkElement felt_result = GetParent(felt, typeof(DataGridCell));
if (felt_result != null)
{
DataGridCell cell = (DataGridCell)felt_result;
//cell.Background = new SolidColorBrush(Color.FromArgb(255, 196, 219, 249));
cell.Background = new SolidColorBrush(Colors.Red);
}
}
}
}
}
}
my value converter:
public class EmailJobStatusConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (value.ToString()=="Stopped") ?
new SolidColorBrush(Colors.Red) :
new SolidColorBrush(Colors.Green);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
SolidColorBrush resultColor = value as SolidColorBrush;
if (resultColor.Color == Colors.Green)
{
return "Green";
}
else
return "Red";
}
}

how to make an button not visible when the image is also not visable in datagrid

i have an requirment based on the value 0,1 i am showing the image.
if the value is 0 i am not showing the image.
if the value is 1 i am showing the image.
but here when i am not showing the image for the row. i want even the button to be not shown?
now i need even the button not to be shown when image is not shown. on that row
how can i solve this issue
link to show how the screen shot
this is my xaml code. its works
<Button x:Name="myButton"
Click="myButton_Click">
<StackPanel Orientation="Horizontal">
<Image Margin="2, 2, 2, 2" x:Name="imgMarks" Stretch="Fill" Width="12" Height="12"
Source="Images/detail.JPG"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Visibility="{Binding Level, Converter={StaticResource LevelToVisibility}}"
/>
</StackPanel>
</Button>
this is my xaml code
<UserControl x:Class="SLGridImage.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sdk="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
xmlns:local="clr-namespace:SLGridImage"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" >
<UserControl.Resources>
<local:LevelToVisibilityConverter x:Key="LevelToVisibility" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<sdk:DataGrid x:Name="dgMarks" CanUserResizeColumns="False" SelectionMode="Single"
AutoGenerateColumns="False"
VerticalAlignment="Top"
ItemsSource="{Binding MarkCollection}"
IsReadOnly="True"
Margin="13,44,0,0"
RowDetailsVisibilityMode="Collapsed" Height="391"
HorizontalAlignment="Left" Width="965"
VerticalScrollBarVisibility="Visible" >
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="myButton"
Click="myButton_Click">
<StackPanel Orientation="Horizontal">
<Image Margin="2, 2, 2, 2" x:Name="imgMarks" Stretch="Fill" Width="12" Height="12"
Source="Images/detail.JPG"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Visibility="{Binding Level, Converter={StaticResource LevelToVisibility}}"
/>
</StackPanel>
</Button>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="Name" >
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate >
<Border>
<TextBlock Text="{Binding Name}" />
</Border>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="Marks" Width="80">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border>
<TextBlock Text="{Binding Marks}" />
</Border>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
</UserControl>
in .cs code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace SLGridImage
{
public partial class MainPage : UserControl
{
private MarksViewModel model = new MarksViewModel();
public MainPage()
{
InitializeComponent();
this.DataContext = model;
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
}
}
public class MarksViewModel : INotifyPropertyChanged
{
public MarksViewModel()
{
markCollection.Add(new Mark() { Name = "ABC", Marks = 23, Level = 0 });
markCollection.Add(new Mark() { Name = "XYZ", Marks = 67, Level = 1 });
markCollection.Add(new Mark() { Name = "YU", Marks = 56, Level = 0 });
markCollection.Add(new Mark() { Name = "AAA", Marks = 89, Level = 1 });
}
private ObservableCollection<Mark> markCollection = new ObservableCollection<Mark>();
public ObservableCollection<Mark> MarkCollection
{
get { return this.markCollection; }
set
{
this.markCollection = value;
OnPropertyChanged("MarkCollection");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public class Mark
{
public string Name { get; set; }
public int Marks { get; set; }
public int Level { get; set; }
}
public class LevelToVisibilityConverter : System.Windows.Data.IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Visibility isVisible = Visibility.Collapsed;
if ((value == null))
return isVisible;
int condition = (int)value;
isVisible = condition == 1 ? Visibility.Visible : Visibility.Collapsed;
return isVisible;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
}
looking for an solution .please help me out
thanks
prince
Use element binding to bind to the Visibility property on the image:
<Button x:Name="myButton" Visibility={Binding Visibility, ElementName=imgMarks} Click="myButton_Click" >
Edit: i just reviewed your XAML and realised that the image was the button content - why don't you move this line:
Visibility="{Binding Level, Converter={StaticResource LevelToVisibility}}"
up to the button instead of having it on the image?