I'm using a carouselview to display a series of images. When I load one I should go to another activity.
What is happening is that inside the carrouselview it does not detect tapgesture.
I read the documentation and says to use the command instead of tapped.
But I'm doing something wrong so he doesn't detect the command.
My xaml page(Report):
<!--Cartão das fotos-->
<Frame x:Name="cartaoFerida" HorizontalOptions="FillAndExpand" BackgroundColor="{StaticResource ferida}" Margin="8,16,8,0" Padding="6">
<Frame.HasShadow>
<OnPlatform x:TypeArguments="x:Boolean" >
<On Platform="Android" Value="true"/>
<On Platform="iOS" Value="false"/>
</OnPlatform>
</Frame.HasShadow>
<StackLayout Orientation="Vertical" HorizontalOptions="Fill">
<StackLayout Orientation="Horizontal">
<StackLayout HorizontalOptions="StartAndExpand" Orientation="Horizontal" >
<Label x:Name="CartaoTituloReport" Margin="20,18,0,0" TextColor="{StaticResource white}" FontSize="16" FontAttributes="Bold">
</Label>
</StackLayout>
<StackLayout HorizontalOptions="End" Orientation="Horizontal" Margin="0,0,-24,0" >
<Frame BackgroundColor="{StaticResource white}" HeightRequest="20" WidthRequest="100" CornerRadius="12" Margin="8,20,8,8" Padding="2" HasShadow="False">
<Label x:Name="LabelEstadoFerida" Margin="8,0,0,0" Text="{translator:Translate Aberto}" TextColor="{StaticResource ferida}" VerticalOptions="Center" FontSize="12" FontAttributes="Bold" />
</Frame>
</StackLayout>
</StackLayout>
<RelativeLayout HorizontalOptions="Center" HeightRequest="220" WidthRequest="330">
<controls:CarouselViewControl x:Name="Carrousel" Orientation="Horizontal" HorizontalOptions="Center" ItemsSource="{Binding Interventions}" HeightRequest="220" WidthRequest="330" Margin="0,16,0,0" ShowIndicators="True" IndicatorsTintColor="{StaticResource Unselected}" CurrentPageIndicatorTintColor="{StaticResource white}" >
<controls:CarouselViewControl.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.ViewItemsDetailsCommand, Source={x:Reference Name=Carrousel}}"
CommandParameter="{Binding}"/>
</controls:CarouselViewControl.GestureRecognizers>
<controls:CarouselViewControl.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Vertical" >
<Label Text="{Binding woundPhoto[0].createdAt}" TextColor="{StaticResource white}" FontAttributes="Bold" FontSize="12" HorizontalOptions="Center"/>
<RelativeLayout WidthRequest="220" HeightRequest="165" VerticalOptions="Center" HorizontalOptions="Center" >
<Image x:Name="Imagem" Source="{Binding woundPhoto[0].photoUri }" Aspect="AspectFill" WidthRequest="220" HeightRequest="165">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference Carrousel}, Path=BindingContext.Command_ImageTapped}"/>
</Image.GestureRecognizers>
</Image>
<StackLayout WidthRequest="220" HeightRequest="165" Orientation="Horizontal" >
<Image x:Name="CameraImage" WidthRequest="22" HeightRequest="22" HorizontalOptions="EndAndExpand" VerticalOptions="StartAndExpand" Margin="0,8,0,0">
<Image.Source>
<OnPlatform x:TypeArguments="ImageSource">
<On Platform="Android" Value="ic_camera.xml"/>
<On Platform="iOS" Value="ic_camera.png"/>
</OnPlatform>
</Image.Source>
</Image>
<Label x:Name="Index" Text="{Binding woundPhoto.Count}" TextColor="{StaticResource white}" FontSize="14" FontFamily="{StaticResource RegularFontFamily} " VerticalOptions="StartAndExpand" HorizontalOptions="End" Margin="0,8,8,0"/>
</StackLayout>
</RelativeLayout>
</StackLayout>
</DataTemplate>
</controls:CarouselViewControl.ItemTemplate>
</controls:CarouselViewControl>
</RelativeLayout>
</StackLayout>
</Frame>
My Viewmodel:
public class CarrouselView : INotifyPropertyChanged
{
#region Property
public event PropertyChangedEventHandler PropertyChanged;
public DelegateCommand ViewItemsDetailsCommand => new DelegateCommand(On_ImageTapped);
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(storage, value))
{
return false;
}
storage = value;
OnPropertyChanged(propertyName);
return true;
}
private void On_ImageTapped()
{
Console.WriteLine("ouuuuuuuuuuuuuuuuuuuuuuuuuuuu");
}
#endregion
public ObservableCollection<Classes.Intervention> Interventions { get; }
public CarrouselView(List<Classes.Intervention> intervention)
{
for(int i =0; i < intervention.Count; i++)
{
for(int j = 0; j< intervention[i].woundPhoto.Count; j++)
{
intervention[i].woundPhoto[j].createdAt = DateTime.Parse(intervention[i].woundPhoto[j].createdAt.ToString()).ToString("dd.MM.yyyy");
}
}
Interventions = new ObservableCollection<Classes.Intervention>(intervention);
}
}
My backend:
try
{
var getHistoryWound = await Servicos.Servicos.GetWound(conversations);
Wound = getHistoryWound;
if (getHistoryWound != null)
{
//As data no formato dd.MM.yyyy data da foto e da proxima intervencao
DataFoto.Text = DateTime.Parse(getHistoryWound.result.woundDate.ToString()).ToString("dd.MM.yyyy");
if(getHistoryWound.result.nextIntervention != null)
ProximaIntervencao.Text = DateTime.Parse(getHistoryWound.result.nextIntervention.ToString()).ToString("dd.MM.yyyy");
//O tipo da ferida
CartaoTituloReport.Text = getHistoryWound.result.intervention[0].typology.ToUpper();
//Date de admissao
if (getHistoryWound.result.isPresentOnAdmission)
RespostaAdmissao.Text = Languages.AppResources.Sim;
else
RespostaAdmissao.Text = Languages.AppResources.Nao;
BindingContext = new ViewModels.CarrouselView(getHistoryWound.result.intervention);
//Caso a ferida esteja fechada, muda a cor da label e o fundo
if (getHistoryWound.result.isClosed)
{
cartaoFerida.BackgroundColor = Color.FromHex("#FF3A3A3A");
LabelEstadoFerida.Text = Languages.AppResources.Fechado;
LabelEstadoFerida.TextColor = Color.FromHex("#FF3A3A3A");
}
if (getHistoryWound.result.intervention[0].category == "null")
{
Categoria.IsVisible = false;
CategoriaLine.IsVisible = false;
}
else
{
Categoria.IsVisible = true;
CategoriaLine.IsVisible = true;
switch (getHistoryWound.result.intervention[0].category)
{
case "1":
CategoriaNivel.Text = "I";
break;
case "2":
CategoriaNivel.Text = "II";
break;
case "3":
CategoriaNivel.Text = "III";
break;
case "4":
CategoriaNivel.Text = "IV";
break;
case "5":
CategoriaNivel.Text = "V";
break;
}
}
//Posicao da imagem
Carrousel.Position = getHistoryWound.result.intervention.Count - 1;
//observações da localização
if(getHistoryWound.result.note == null || getHistoryWound.result.note == "null")
{
CartaoObservacoesLocalizacao.IsVisible = false;
}
else
{
CartaoObservacoesLocalizacao.IsVisible = true;
var position = getHistoryWound.result.intervention.Count;
ObservacoesTitulo.Text = Languages.AppResources.Observacoes + " " + getHistoryWound.result.intervention[position - 1].createdAt.ToString("dd.MM.yyyy");
ObservacoesLocalizacao.Text = getHistoryWound.result.note;
}
//Maximo da datas
DataDe.MaximumDate = DateTime.Now;
DataAte.MaximumDate = DateTime.Now;
return true;
}
return false;
}
catch (Exception)
{
await DisplayAlert(Languages.AppResources.Notifications, Languages.AppResources.ErrorOccurred, "Ok");
return false;
}
I think your problem is the binding path and source you set is wrong, I wrote a demo and the binding works on my side, here is the code:
<CarouselView>
<CarouselView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Baboon</x:String>
<x:String>Capuchin Monkey</x:String>
<x:String>Blue Monkey</x:String>
<x:String>Squirrel Monkey</x:String>
<x:String>Golden Lion Tamarin</x:String>
<x:String>Howler Monkey</x:String>
<x:String>Japanese Macaque</x:String>
</x:Array>
</CarouselView.ItemsSource>
<CarouselView.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=ViewItemsDetailsCommand}"
CommandParameter="{Binding}"/>
</CarouselView.GestureRecognizers>
</CarouselView>
And in code behind:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new CarouselViewModel();
}
}
public class CarouselViewModel : INotifyPropertyChanged
{
#region Property
public event PropertyChangedEventHandler PropertyChanged;
public Command ViewItemsDetailsCommand => new Command(On_ImageTapped);
private void On_ImageTapped()
{
Console.WriteLine("ouuuuuuuuuuuuuuuuuuuuuuuuuuuu");
}
#endregion
public CarouselViewModel()
{
}
}
So, change your binding like below code may work:
<controls:CarouselViewControl.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ViewItemsDetailsCommand}"
CommandParameter="{Binding}"/>
</controls:CarouselViewControl.GestureRecognizers>
Related
I have 2 ContentView in MyWordPage.Xaml which are MyWordListView and AddWordsView
My MyWordPage.Xaml looks like this :
<ContentView x:Name="MyWordListView" >
<CollectionView x:Name="ListOfWords" IsVisible="False"
SelectionMode="Single" >
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout >
<Label Text="{Binding .}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentView>
<ContentView IsVisible="False" x:Name="AddWordsView" />
<pv:PancakeView HorizontalOptions="End" VerticalOptions="End" Margin="0,0,10,150" Padding="10" CornerRadius="10">
<Image HeightRequest="30" WidthRequest="30" Aspect="AspectFit" />
<pv:PancakeView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnChangeViewButton" />
</pv:PancakeView.GestureRecognizers>
</pv:PancakeView>
<Grid/>
If MyWordListView is visible, AddWordsView is not visible and vise versa.
The App starts with MyWordListPage visible and MyWordPage.xaml.cs looks like this:
public MyWordPage()
{
InitializeComponent();
// My second content view AddWordsView take content form a content page
// this content page name is MyAddWordPage
AddWordsView.Content = new MyAddWordPage().Content;
//My list of words
ListOfWords.ItemsSource = new List<string>()
{
"New York",
"London",
"Mumbai",
"Chicago"
};
}
//I navigate between the 2 View With an Overlay Button that make
//each one of View visible thanks to a boolean
bool ViewChange=false;
void OnChangeViewButton(System.Object sender, System.EventArgs e)
{
if (ViewChange==false)
{
AddWordsView.IsVisible=true;
MyWordListView.IsVisible=false;
ViewChange=!ViewChange;
}
else
{
AddWordsView.IsVisible=false;
MyWordListView.IsVisible=true;
ViewChange=!ViewChange;
}
}
OnUpdateMyList()
{
// Here I do things to refresh my list
}
MyAddWordPage.xaml.cs looks like this :
public MyWordPage()
{
InitializeComponent();
}
void OnInsertWord(System.Object sender, System.EventArgs e)
{
}
What I would like to do :
In MyAddWordPage.xaml.cs when clicking on a button to launch the function OnInsertWord() I would like to launch the function OnUpdateMyList() in MyWordPage.xaml.cs in order to refresh My collectionView in MyWordListView
Thanks for your help
According to your requirement, you can achieve this by overriding OnAppearing method.
The OnAppearing method is executed after the ContentPage is laid out, but just before it becomes visible.So, you can rebind the list to the collectionview in this method. Therefore, this is a good place to set the content of Xamarin.Forms views.
Here is the code in MyWordPage.xaml.cs:
public MainPage()
{
InitializeComponent();
// My second content view AddWordsView take content form a content page
// this content page name is MyAddWordPage
AddWordsView.Content = new MyAddWordPage().Content;
//My list of words
}
//Create a list
List<string> list = new List<string>()
{
"New York",
"London",
"Mumbai",
"Chicago"
};
protected override void OnAppearing()
{
base.OnAppearing();
ListOfWords.ItemsSource = list;
}
//I navigate between the 2 View With an Overlay Button that make
//each one of View visible thanks to a boolean
bool ViewChange = false;
void OnChangeViewButton(System.Object sender, System.EventArgs e)
{
if (ViewChange == false)
{
AddWordsView.IsVisible = true;
MyWordListView.IsVisible = false;
ViewChange = !ViewChange;
}
else
{
AddWordsView.IsVisible = false;
MyWordListView.IsVisible = true;
ViewChange = !ViewChange;
}
}
}
Here is the code in MyWordPage.Xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App5.MainPage">
<StackLayout>
<StackLayout x:Name="MyWordListView">
<CollectionView x:Name="ListOfWords" SelectionMode="Single" >
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout >
<Label Text="{Binding .}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
<ContentView IsVisible="False" x:Name="AddWordsView" >
<Label Text="Here is the text."></Label>
</ContentView>
<StackLayout>
<Button Clicked="OnChangeViewButton"></Button>
</StackLayout>
</StackLayout>
</ContentPage>
I have a grouped ObservableCollection which is binded to a ListView.
I have a number of StackLayout inside the ListView who's visibility changes upon the ListView tapp.
All others properties inside reacts to the PropertyChange but the visibility of the StackLayout doesnot.
All this is done on UI Thread.
Can anyone else has/had this issue?
Updating the UI inside a loop
Device.BeginInvokeOnMainThread(() =>
{
item.Effort = SelectedTaskItem.Effort;
finalEffortDouble = SelectedTaskItem.Effort + finalEffortDouble - previousEffort;
item.IsSaved = true;
item.IsNotSaved = false;
item.EffortsString = SelectedTime.ToString("hh':'mm") + " h";
TotalEffortsHoursString = TimeSpan.FromHours(finalEffortDouble + TotalEffortsHours).ToString("hh'.'mm") + " hrs";
});
IsSaved , IsNotSaved are bool which are binded to the StackLayout visibility property inside a ListView.
<StackLayout Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" IsVisible="{Binding IsNotSaved,Mode=TwoWay}" Padding="0" Margin="0" HorizontalOptions="FillAndExpand">
<Label Text="{Binding TaskName}" FontAttributes="Bold" FontSize="16" LineBreakMode="TailTruncation" />
<Label Text="Enter time spent on this task daily" FontSize="12" />
</StackLayout>
<StackLayout Grid.Row="0" Grid.Column="1" IsVisible="{Binding IsNotSaved,Mode=TwoWay}" Orientation="Horizontal" VerticalOptions="CenterAndExpand" Spacing="10" HorizontalOptions="End" Padding="0" Margin="0">
<ffimageloading:CachedImage Source="tsplus">
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer Tapped="EditTime_Tapped" CommandParameter="{Binding .}" />
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
</StackLayout>
<StackLayout x:Name="Is1" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" IsVisible="{Binding IsSaved,Mode=TwoWay}" Padding="0" Margin="0" HorizontalOptions="FillAndExpand">
<Label Text="{Binding TaskName}" FontAttributes="Bold" FontSize="16" LineBreakMode="TailTruncation" />
<StackLayout Orientation="Horizontal" Padding="0" Margin="0" HorizontalOptions="FillAndExpand">
<Label Text="Tap on time to edit" FontSize="12" />
<ffimageloading:CachedImage Source="savedtag" WidthRequest="60" HeightRequest="20" />
</StackLayout>
</StackLayout>
<StackLayout x:Name="Is2" Grid.Row="0" Grid.Column="1" IsVisible="{Binding IsSaved,Mode=TwoWay}" VerticalOptions="CenterAndExpand" HorizontalOptions="End" Padding="0" Margin="0">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="EditTime_Tapped" CommandParameter="{Binding .}" />
</StackLayout.GestureRecognizers>
<Label Text="{Binding EffortsString}" FontSize="24" VerticalOptions="Center" TextColor="{x:Static common:ColorResources.NavigationBarColor}" />
</StackLayout>
Model of the binded ObservableCollection
public class ProjectListWithTasksModel : List<TaskModel>
{
public List<TaskModel> Tasks => this;
public string ProjectName { get; set; }
}
Task Model:
public class TaskModel : ObservableObject
{
public string TaskGUID { get; set; }
public string TaskName { get; set; }
public string EffortStatus { get; set; }
public string TaskStatus { get; set; }
private double _Effort;
public double Effort
{
get { return _Effort; }
set
{
_Effort = value;
RaisePropertyChanged("Effort");
}
}
public DateTime EffortDate { get; set; }
public DateTime EffortDay { get; set; }
//UI Models : Used for UI Changes
public string ProjectID { get; set; }
public DateTime LastWorkingDay { get; set; }
private bool _IsSaved;
public bool IsSaved
{
get
{
if (this.EffortStatus.Contains("10"))
_IsSaved = true;
else
_IsSaved = false;
return _IsSaved;
}
set
{
_IsSaved = value;
RaisePropertyChanged("IsSaved");
}
}
public bool IsSubmitted
{
get
{
if (this.EffortStatus.Contains("20"))
{
return true;
//&& LastWorkingDay.Date >= DateTime.Now.Date
}
else
return false;
}
}
public bool IsApproved
{
get
{
if (this.EffortStatus.Contains("30"))
{
return true;
}
else
return false;
}
}
public bool IsRejected
{
get
{
if (this.EffortStatus.Contains("40"))
{
return true;
}
else
return false;
}
}
public string _EffortsString;
public string EffortsString
{
get
{
_EffortsString = TimeSpan.FromHours(Effort).ToString("hh':'mm") + " h";
return _EffortsString;
}
set
{
_EffortsString = value;
RaisePropertyChanged("EffortsString");
}
}
private bool _IsNotSaved;
public bool IsNotSaved
{
get
{
if (this.EffortStatus.Contains("0 "))
_IsNotSaved = true;
else
_IsNotSaved = false;
return _IsNotSaved;
}
set
{
_IsNotSaved = value;
RaisePropertyChanged("IsNotSaved");
}
}
}
I think the problem is that IsSaved depends by EffortStatus, so you should not have a "Set" for "IsSaved". I think you should "RaiseProperty" IsSaved (and IsNotSaved) when EffortStatus i set. Something like:
public string EffortStatus
{
get
{
return _EffortStatus;
}
set
{
_EffortStatus= value;
if (_EffortStatus.Contains("10"))
IsSaved = true;
else
IsSaved = false;
RaisePropertyChanged("EffortStatus");
RaisePropertyChanged("IsSaved");
}
}
I have that show/hide pass feature and it works just fine. One of my views ilustrated below has a security code that effect is also applied on Entry Text that has property 'IsEnabled=False'. Right now when I click on an eye nothing happens.
Is there any way to get it working when text entry is not enabled?
<StackLayout Grid.Row="1" IsVisible="{Binding IsPINSectionVisible}">
<Label
Style="{StaticResource MessageLabelStyle}"
Text="{i18n:Translate Pin_Text}">
</Label>
</StackLayout>
<StackLayout Grid.Row="2" IsVisible="{Binding IsPINSectionVisible}">
<Entry Text="{Binding PIN.Value, Mode=TwoWay}"
IsEnabled="False"
IsPassword="True"
Placeholder="{i18n:Translate Pin_Title}">
<Entry.Style>
<OnPlatform x:TypeArguments="Style"
Android="{StaticResource EntryStyle}" />
</Entry.Style>
<Entry.Behaviors>
<behaviors:EventToCommandBehavior
EventName="TextChanged"
Command="{Binding ValidatePINCommand}" />
</Entry.Behaviors>
<Entry.Effects>
<effects:ShowHidePassEffect />
</Entry.Effects>
<Entry.Triggers>
<DataTrigger
TargetType="Entry"
Binding="{Binding PIN.IsValid}"
Value="False">
<Setter Property="behaviors:LineColorBehavior.LineColor"
Value="{StaticResource ErrorColor}" />
<Setter Property="Entry.PlaceholderColor"
Value="{StaticResource ErrorColor}" />
</DataTrigger>
</Entry.Triggers>
</Entry>
And Android Effect class:
public class ShowHidePassEffect : PlatformEffect
{
protected override void OnAttached()
{
ConfigureControl();
}
protected override void OnDetached()
{
}
private void ConfigureControl()
{
EditText editText = ((EditText)Control);
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.pass_show_24, 0);
editText.SetOnTouchListener(new OnDrawableTouchListener());
}
}
public class OnDrawableTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
{
public bool OnTouch(Android.Views.View v, MotionEvent e)
{
if (v is EditText && e.Action == MotionEventActions.Up)
{
EditText editText = (EditText)v;
if (e.RawX >= (editText.Right - editText.GetCompoundDrawables()[2].Bounds.Width()))
{
if (editText.TransformationMethod == null)
{
editText.TransformationMethod = PasswordTransformationMethod.Instance;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.pass_show_24, 0);
}
else
{
editText.TransformationMethod = null;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.pass_hide_24, 0);
}
return true;
}
}
return false;
}
}
And picture to ilustrate the view:
I have a DataGrid where each row has a delete button. If I set the Command="Delete" attribute on the Delete button element in XAML, the button is disabled at runtime. Why??
XAML:
<Page x:Class="AxureExport.TargetPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:AxureExport"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
Title="Define Export Targets"
Loaded="Page_Loaded">
<Page.Resources>
<Style TargetType="{x:Type DataGridCell}">
<EventSetter Event="PreviewMouseLeftButtonDown"
Handler="DataGridCell_PreviewMouseLeftButtonDown" />
</Style>
</Page.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="7" />
<ColumnDefinition Width="65" />
<ColumnDefinition Width="458*" />
<ColumnDefinition Width="47" />
<ColumnDefinition Width="10" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="7" />
<RowDefinition Height="63*" />
</Grid.RowDefinitions>
<!-- target file -->
<TextBlock Name="textBlock3"
Text="2. Select the location where you want to save the string files:"
Height="23"
HorizontalAlignment="Left"
Margin="5,0,0,0"
VerticalAlignment="Top"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="4"
Width="441" />
<TextBlock Name="textBlock4"
Text="(Warning: This tool overwrites files in the target folder.)"
Height="16"
HorizontalAlignment="Left"
Margin="54,15,0,0"
VerticalAlignment="Top"
Width="256"
FontStyle="Italic"
FontWeight="Light"
FontSize="10"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="2" />
<TextBlock Name="textBlock5"
Text="Target:"
Height="23"
HorizontalAlignment="Left"
Margin="22,30,0,238"
VerticalAlignment="Center"
Grid.Row="1"
Grid.Column="1" />
<!-- ExportTargets Datagrid -->
<DataGrid Name="ExportTargets"
AutoGenerateColumns="False"
Grid.Column="2"
Grid.Row="1"
Margin="0,71,0,63"
ItemsSource="{Binding Path=., Mode=TwoWay}"
SelectionUnit="Cell"
GridLinesVisibility="None"
RowDetailsVisibilityMode="Collapsed"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserResizeRows="False"
RowHeaderWidth="40"
IsSynchronizedWithCurrentItem="True"
HorizontalScrollBarVisibility="Disabled"
CanUserAddRows="True"
CanUserDeleteRows="True">
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}"
Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}"
Color="Black" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsXML, Mode=TwoWay}"
Header="XML"
CanUserSort="False"
CanUserReorder="False" />
<DataGridCheckBoxColumn Binding="{Binding IsProperty, Mode=TwoWay}"
Header="Property"
CanUserSort="False"
CanUserReorder="False" />
<DataGridTextColumn Binding="{Binding FolderName, Mode=TwoWay}"
Header="Folder"
Width="*"
CanUserReorder="False"
IsReadOnly="False" />
<DataGridTemplateColumn Header="Browse">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="Browse"
Command="{Binding BrowseCommand}"
HorizontalAlignment="Center"
Width="20">...</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Delete" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="Delete"
Command="{x:Static DataGrid.DeleteCommand}"
HorizontalAlignment="Center"
Width="20"
IsEnabled="True">X</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button Name="NextButton"
Content="Next"
Grid.Column="2"
Grid.ColumnSpan="2"
Grid.Row="1"
Margin="0,0,2,12"
Width="100"
Height="40"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Click="NextButton_Click" />
</Grid>
</Page>
Code-behind:
// DataTable
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace AxureExport {
/// <summary>
/// Interaction logic for TargetPage.xaml
/// </summary>
public partial class TargetPage : Page {
FrameWindow _frame;
//ExportTargetInfos _eti;
public TargetPage(FrameWindow frame) {
InitializeComponent();
_frame = frame;
_frame.ExportTargets = new ExportTargetInfos(Properties.Settings.Default.ExportTargetHistory);
this.DataContext = _frame.ExportTargets;
}
//
// enable editing on single-click
private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
DataGridCell cell = sender as DataGridCell;
if (!cell.IsEditing) {
if (!cell.IsFocused)
cell.Focus();
if (!cell.IsSelected)
cell.IsSelected = true;
}
}
private void Page_Loaded(object sender, RoutedEventArgs e) {
}
private void NextButton_Click(object sender, RoutedEventArgs e) {
Properties.Settings.Default.ExportTargetHistory = _frame.ExportTargets.GetExportTargets();
_frame.NavigateTo(typeof(ExportPage));
}
}
}
ViewModel:
using System;
using System.Collections.ObjectModel; // ObservibleCollection<>
using System.Collections.Specialized; // StringCollection
using System.ComponentModel; // INotifyPropertyChanged
namespace AxureExport {
public class ExportTargetInfos : ObservableCollection<ExportTargetInfo> {
const char _SEP = '|'; // field seperator character
// default constructor
public ExportTargetInfos() : base() {
}
// copy constructors
public ExportTargetInfos(ExportTargetInfos etis) : base() {
if (etis == null) return;
foreach (ExportTargetInfo eti in etis) {
this.Add(new ExportTargetInfo(eti.FolderName, eti.IsXML, eti.IsProperty));
}
}
public ExportTargetInfos(StringCollection sc) : base() {
if (sc == null) return;
foreach (string s in sc)
Add(ParseExportTarget(s));
}
public StringCollection GetExportTargets() {
StringCollection sc = new StringCollection();
foreach (ExportTargetInfo et in this)
sc.Add(BuildExportTarget(et));
return sc;
}
// create a string from an ExportTarget (for persistance)
private static string BuildExportTarget(ExportTargetInfo et) {
return et.FolderName + _SEP + et.IsXML.ToString() + _SEP + et.IsProperty.ToString();
}
// create an ExportTarget from an unparsed string (for persistance)
private static ExportTargetInfo ParseExportTarget(string s) {
int count = s.Split(_SEP).Length - 1;
string[] items = s.Split(new[] { _SEP }, StringSplitOptions.None);
string name = (count < 1 ? String.Empty : items[0]);
bool isXML = (count > 0 ? Convert.ToBoolean(items[1]) : false);
bool isProp = (count > 1 ? Convert.ToBoolean(items[2]) : false);
return new ExportTargetInfo(name, isXML, isProp);
}
}
//
// represents an export target (folder plus options) in it's parsed form
public class ExportTargetInfo : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public IDelegateCommand BrowseCommand { protected set; get; }
// default constructor is needed to enable datagrid to add rows
public ExportTargetInfo() {
_folderName = String.Empty;
_isXML = false;
_isProperty = false;
this.BrowseCommand = new DelegateCommand(ExecuteBrowse, CanExecuteBrowse);
}
public ExportTargetInfo(string targetFolderName, bool isXML, bool isProperties) {
_folderName = targetFolderName;
_isXML = isXML;
_isProperty = isProperties;
this.BrowseCommand = new DelegateCommand(ExecuteBrowse, CanExecuteBrowse);
}
private string _folderName;
public string FolderName {
get { return _folderName; }
set { SetProperty<string>(ref _folderName, value, #"FolderName"); }
}
private bool _isXML;
public bool IsXML {
get { return _isXML; }
set { SetProperty<bool>(ref _isXML, value, #"IsXML"); }
}
private bool _isProperty;
public bool IsProperty {
get { return _isProperty; }
set { SetProperty<bool>(ref _isProperty, value, #"IsProperty"); }
}
// browse button for selected row clicked
void ExecuteBrowse(object param) {
// use WPF-WinForms interop (:-p)
var folderDialog = new System.Windows.Forms.FolderBrowserDialog();
folderDialog.Description = "Please designate the target folder";
folderDialog.SelectedPath = FolderName;
folderDialog.ShowNewFolderButton = true;
if (folderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
FolderName = folderDialog.SelectedPath;
}
bool CanExecuteBrowse(object param) {
return true;
}
protected bool SetProperty<T>(ref T storage, T value, string propertyName = null) {
if (object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged(string propertyName) {
if (PropertyChanged != null)
PropertyChanged( this, new PropertyChangedEventArgs(propertyName));
}
}
}
Does anyone have insight as to what's the cause?
This isn't a solution, but through trial & error I discovered the disabled delete button behavior is caused by the SelectionUnit="Cell" setting in the DataGrid. Setting it to FullRow enables the delete row button.
<Button Name="NextButton" isEnable = "true" />
I'm making an application in Silverlight 4. I am facing a problem, I need to change a particular combobox into textbox programmatically when a particular column value(using combobox) of the same row is changed.I need to change this on event cellEditEnded.
Please note that I need to change celleditingtemplate combobox to textbox not celltemplate textblock.
This my Column where I need to take the decision of its combo box selected value.
<sdk:DataGridTemplateColumn Header="Instruction Type"
CanUserResize="False" CanUserReorder="False">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Margin="2" Text="{Binding operationType}" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="instruction" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
This Column comboBox need to change to textbox here:
<sdk:DataGridTemplateColumn Header="Destination">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Margin="2" Text="{Binding destination}" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="destination"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
C# code:
public class Instruction
{
public string operationType { get; set; }
public string destination { get; set; }
}
private void myGrid_CellEditEnded(object sender, DataGridCellEditEndedEventArgs e)
{
DataGrid obj = (DataGrid)sender;
Instruction obj1 = (Instruction)obj.SelectedItem;
if (e.Column.Header.ToString() == "Instruction Type")
{
if (obj1.operationType == "ADD" || obj1.operationType == "SUB")
{
// Here I need Require Code ????/
}
}
}
I m waitng for anyone Genius who help me out ..
Here is a working example http://anzensoft.smtp.ru/FlashKiller2/DataGridTrickTestPage.html
And here is the source code http://cid-a1de71e9f2ae2f82.office.live.com/self.aspx/.Public/DataGridTrick.zip
xaml code
<Grid x:Name="LayoutRoot" Background="White">
<sdk:DataGrid x:Name="dataGrid1" AutoGenerateColumns="False"
PreparingCellForEdit="dataGrid1_PreparingCellForEdit">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Instruction Type">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Margin="2" Text="{Binding operationType}" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="instruction"
SelectedValue="{Binding operationType, Mode=TwoWay}">
<s:String>ADD</s:String>
<s:String>MUL</s:String>
</ComboBox>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn Header="Destination">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Margin="2" Text="{Binding destination}" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
<sdk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<Grid>
<ComboBox x:Name="destinationComboBox"
SelectedValue="{Binding destination, Mode=TwoWay}">
<s:String>sdas</s:String>
<s:String>dasdasdasd</s:String>
</ComboBox>
<TextBox x:Name="destinationTextBox"
Text="{Binding destination, Mode=TwoWay}"
Visibility="Collapsed"/>
</Grid>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellEditingTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
C# code
namespace DataGridTrick
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
dataGrid1.ItemsSource = new List<Instruction>()
{
new Instruction(){operationType = "ADD", destination ="sdas"},
new Instruction(){operationType = "ADD", destination = "dasdasdasd"}
};
}
private void dataGrid1_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
{
if ((string)e.Column.Header == "Destination")
{
var tb = e.EditingElement.FindName("destinationTextBox") as TextBox;
var cb = e.EditingElement.FindName("destinationComboBox") as ComboBox;
var instruction = e.EditingElement.DataContext as Instruction;
if (tb == null || cb == null || instruction == null)
{
throw new
Exception("Something wrong here.. this dosen't have to happen!!");
}
else
{
if (instruction.operationType == "MUL")
{
tb.DataContext = e.EditingElement.DataContext;
cb.DataContext = null;
tb.Visibility = System.Windows.Visibility.Visible;
cb.Visibility = System.Windows.Visibility.Collapsed;
}
else
{
tb.DataContext = null;
cb.DataContext = e.EditingElement.DataContext;
tb.Visibility = System.Windows.Visibility.Collapsed;
cb.Visibility = System.Windows.Visibility.Visible;
}
}
}
}
}
public class Instruction
{
public string operationType { get; set; }
public string destination { get; set; }
}
}