I've read about messaging, triggers, behaviors, etc. ... all seems a bit overkill for what I am trying to accomplish.
I have a repeating data entry screen in xaml that has 1 picker, 2 entries, and 1 button. The picker, once a value is selected, keeps that selection. The 1st entry does the same as the picker. The 2nd entry is the one that is always getting new values.
I want to collect the filled in values on click of the button and then clear the last entry field of its data and put focus back on that entry so the user can enter a new value and hit save. repeat repeat repeat etc.
I understand the MVVM model and theory - but I just want to put the focus on an entry field in the xaml view and am completely stumped.
EDIT to add code samples
view.xaml:
<StackLayout Spacing="5"
Padding="10,10,10,0">
<Picker x:Name="Direction"
Title="Select Direction"
ItemsSource="{Binding Directions}"
ItemDisplayBinding="{Binding Name}"
SelectedItem="{Binding SelectedDirection}"/>
<Label Text="Order"/>
<Entry Text="{Binding Order}"
x:Name="Order" />
<Label Text="Rack"/>
<Entry Text="{Binding Rack}"
x:Name="Rack" />
<Button Text="Save"
Style="{StaticResource Button_Primary}"
Command="{Binding SaveCommand}"
CommandParameter="x:Reference Rack" />
<Label Text="{Binding Summary}"/>
</StackLayout>
viewmodel.cs
public ICommand SaveCommand => new DelegateCommand<View>(PerformSave);
private async void PerformSave(View view)
{
var scan = new Scan()
{
ScanType = "Rack",
Direction = SelectedDirection.Name,
AreaId = 0,
InsertDateTime = DateTime.Now,
ReasonId = 0,
ScanItem = Rack,
OrderNumber = Order,
ScanQty = SelectedDirection.Value,
IsUploaded = false
};
var retVal = _scanService.Insert(scan);
if (!retVal)
{
await _pageDialogService.DisplayAlertAsync("Error", "Something went wrong.", "OK");
}
else
{
view?.Focus();
Rack = string.Empty;
Summary = "last scan was great";
}
}
Error shows up in this section:
private void InitializeComponent() {
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(RackPage));
Direction = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.Picker>(this, "Direction");
Order = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.Entry>(this, "Order");
Rack = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.Entry>(this, "Rack");
}
You can send the Entry as a View parameter to your view model's command. Like that:
public YourViewModel()
{
ButtonCommand = new Command<View>((view) =>
{
// ... Your button clicked stuff ...
view?.Focus();
});
}
And from XAML you call this way:
<Entry x:Name="SecondEntry"
... Entry properties ...
/>
<Button Text="Click Me"
Command="{Binding ButtonCommand}"
CommandParameter="{Reference SecondEntry}"/>
I hope it helps.
You can set the CommandParameter in the XAML and use that in the viewmodel.
In Xaml:
<ContentView Grid.Row="0" Grid.Column="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image Source="downarrow" HeightRequest="15" WidthRequest="15" VerticalOptions="Center" HorizontalOptions="End" Margin="0,0,5,0" />
<ContentView.GestureRecognizers>
<TapGestureRecognizer Command="{Binding SecurityPopupCommand}" CommandParameter="{x:Reference AnswerEntry}"/>
</ContentView.GestureRecognizers>
</ContentView>
In view model:
public ICommand SecurityPopupCommand { get { return new Command(OpenSecurityQuestionPopup); } }
private void OpenSecurityQuestionPopup(object obj)
{
var view = obj as Xamarin.Forms.Entry;
view?.Focus();
}
Not sure you can set the focus of an entry from the XAML, but from the page, you could just use the function Focus of the Entry on the Clicked Event:
saveButton.Clicked += async (s, args) =>
{
//save the data you need here
//clear the entries/picker
yourEntry.Focus();
};
Related
I'm becoming crazy i don't understand why my ObservableCollections have a strange behaviour. I have tabs :
<Grid Grid.Row="1">
<TabControl Grid.Row="1">
<TabItem Header="Posts instagrams">
<DataGrid ItemsSource="{Binding InstagramPhotos, Mode=TwoWay}" />
</TabItem>
<TabItem Header="Shop">
<DataGrid ItemsSource="{Binding ShopPhotos, Mode=TwoWay}" />
</TabItem>
<TabItem Header="Articles">
<DataGrid ItemsSource="{Binding ArticlePhotos, Mode=TwoWay}" />
</TabItem>
</TabControl>
</Grid>
The ObservableCollections are defined like this :
private ObservableCollection<PhotoModel> _instagramPhotos;
public ObservableCollection<PhotoModel> InstagramPhotos
{
get => _instagramPhotos ?? (_instagramPhotos = new ObservableCollection<PhotoModel>());
set
{
_instagramPhotos = value;
RaisePropertyChanged("InstagramPhotos");
}
}
private ObservableCollection<PhotoModel> _shopPhotos;
public ObservableCollection<PhotoModel> ShopPhotos
{
get => _shopPhotos ?? (_shopPhotos = new ObservableCollection<PhotoModel>());
set
{
_shopPhotos = value;
RaisePropertyChanged("ShopPhotos");
}
}
private ObservableCollection<ArticleModel> _articlePhotos;
public ObservableCollection<ArticleModel> ArticlePhotos
{
get => _articlePhotos ?? (_articlePhotos = new ObservableCollection<ArticleModel>());
set
{
_articlePhotos = value;
RaisePropertyChanged("ArticlePhotos");
}
}
I bind commands for adding/update/delete element in each collections. The update work fine on every UI. BUT where it's strange is that the Add event works correctly in first tab but delete doesn't. And in other tab, add event doesn't work but delete works. I clearly don't understand why.
FINALLY found out ! I was using this
DataContext="{Binding Source={StaticResource DataViewModel}}"
So it doesn't update. I put it in <Window.DataContext> tag and works well
Update: Just a reminder, there's a 500 point bonus on this if someone can just show me how to implement this functionality without using Gestures>
I am using a ViewCell and a gesture recognizer to open up a picker with the following code. The ViewCell has a label on the left and a label area on the right that is populated initially when the app starts and later with the picker when the ViewCell is clicked.
XAML
<ViewCell x:Name="ati" Tapped="OpenPickerCommand">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<Grid.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding OpenPickerCommand}"
CommandParameter="{x:Reference atiPicker}" NumberOfTapsRequired="1" />
</Grid.GestureRecognizers>
<local:LabelBodyRendererClass Text="Answer Time Interval" HorizontalOptions="StartAndExpand" />
<Picker x:Name="atiPicker" IsVisible="false" HorizontalOptions="End" SelectedIndexChanged="atiPickerSelectedIndexChanged" ItemsSource="{Binding Times}"></Picker>
<local:LabelBodyRendererClass x:Name="atiLabel" HorizontalOptions="End"/>
</Grid>
</ViewCell>
<ViewCell x:Name="pti" Tapped="OpenPickerCommand">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<Grid.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding OpenPickerCommand}"
CommandParameter="{x:Reference ptiPicker}" NumberOfTapsRequired="1" />
</Grid.GestureRecognizers>
<local:LabelBodyRendererClass Text="Phrase Time Interval" HorizontalOptions="StartAndExpand" />
<Picker x:Name="ptiPicker" IsVisible="false" HorizontalOptions="End" SelectedIndexChanged="ptiPickerSelectedIndexChanged" ItemsSource="{Binding Times}"></Picker>
<local:LabelBodyRendererClass x:Name="ptiLabel" HorizontalOptions="End"/>
</Grid>
</ViewCell>
C# This works for different pickers (ati, bti, pti etc) with CommandParameter
public SettingsPage()
{
InitializeComponent();
BindingContext = new CommandViewModel();
}
void atiPickerSelectedIndexChanged(object sender, EventArgs e)
{
var picker = (Picker)sender;
int selectedIndex = picker.SelectedIndex;
if (selectedIndex != -1)
{
App.DB.UpdateIntSetting(Settings.Ati, selectedIndex);
atiLabel.Text = AS.ati.Text();
}
}
void ptiPickerSelectedIndexChanged(object sender, EventArgs e)
{
var picker = (Picker)sender;
int selectedIndex = picker.SelectedIndex;
if (selectedIndex != -1)
{
App.DB.UpdateIntSetting(Settings.Pti, selectedIndex);
ptiLabel.Text = AS.pti.Text();
}
}
public class CommandViewModel: ObservableProperty
{
public ICommand openPickerCommand;
public CommandViewModel()
{
openPickerCommand = new Command<Picker>(PickerFocus);
//openPickerCommand = new Command(tapped);
}
public ICommand OpenPickerCommand
{
get { return openPickerCommand; }
}
void PickerFocus(Picker param)
{
param.Focus();
}
}
I would like to remove the use of TapGestureRecognizers but I still want to retain the functionality and layout.
It's been suggested to me that it would be better if I used the Tapped event of the ViewCell like this:
Tapped="OnTapped"
Can someone explain in some detail how I could wire this up in C#. Would I be best to code something into the CommandViewModel as well as in the C# backing code. Also can the view model have one method that takes an argument so it could be used to open up different pickers?
An example of how I could do this would be very much appreciated. Note that I don't particularly need to use the CommandViewModel if there is a way that I could do this by coding just in the .cs backing code.
(Sorry for the poor english)
Despite not being best practice, I guess you can do something like this, dismissing the viewmodel:
XAML:
<ViewCell x:Name="ati" Tapped="OpenPickerCommand">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<local:LabelBodyRendererClass Text="Answer Time Interval" HorizontalOptions="StartAndExpand" />
<Picker x:Name="atiPicker"
IsVisible="false"
HorizontalOptions="End"
SelectedIndexChanged="atiPickerSelectedIndexChanged"
ItemsSource="{Binding Times}">
</Picker>
<local:LabelBodyRendererClass x:Name="atiLabel" HorizontalOptions="End"/>
</Grid>
</ViewCell>
<ViewCell x:Name="pti" Tapped="OpenPickerCommand">
<Grid VerticalOptions="CenterAndExpand" Padding="20, 0">
<local:LabelBodyRendererClass Text="Phrase Time Interval" HorizontalOptions="StartAndExpand" />
<Picker x:Name="ptiPicker" IsVisible="false" HorizontalOptions="End" SelectedIndexChanged="ptiPickerSelectedIndexChanged" ItemsSource="{Binding Times}"></Picker>
<local:LabelBodyRendererClass x:Name="ptiLabel" HorizontalOptions="End"/>
</Grid>
</ViewCell>
C#:
private void OpenPickerCommand(object sender, System.EventArgs e)
{
if (sender != null)
{
Picker pkr = sender == ati ? atiPicker : ptiPicker;
pkr.Focus();
}
}
Answering your question "Can the view model have one method that takes an argument?", it is exactly what you're already doing using the 'OpenPickerCommand' method. The problem is that using the ViewCell's public event 'Tapped', you can't set parameters to the delegate handler.
Let me know if it works for you or if you do need some more information.
I hope it helps.
You can solve this with attached properties. Simply define a "behavior" class for ViewCell that adds the Command/Parameter properties.
public static class TappedCommandViewCell
{
private const string TappedCommand = "TappedCommand";
private const string TappedCommandParameter = "TappedCommandParameter";
public static readonly BindableProperty TappedCommandProperty =
BindableProperty.CreateAttached(
TappedCommand,
typeof(ICommand),
typeof(TappedCommandViewCell),
default(ICommand),
BindingMode.OneWay,
null,
PropertyChanged);
public static readonly BindableProperty TappedCommandParameterProperty =
BindableProperty.CreateAttached(
TappedCommandParameter,
typeof(object),
typeof(TappedCommandViewCell),
default(object),
BindingMode.OneWay,
null);
private static void PropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is ViewCell cell)
{
cell.Tapped -= ViewCellOnTapped;
cell.Tapped += ViewCellOnTapped;
}
}
private static void ViewCellOnTapped(object sender, EventArgs e)
{
if (sender is ViewCell cell && cell.IsEnabled)
{
var command = GetTappedCommand(cell);
var parameter = GetTappedCommandParameter(cell);
if (command != null && command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
public static ICommand GetTappedCommand(BindableObject bindableObject) =>
(ICommand)bindableObject.GetValue(TappedCommandProperty);
public static void SetTappedCommand(BindableObject bindableObject, object value) =>
bindableObject.SetValue(TappedCommandProperty, value);
public static object GetTappedCommandParameter(BindableObject bindableObject) =>
bindableObject.GetValue(TappedCommandParameterProperty);
public static void SetTappedCommandParameter(BindableObject bindableObject, object value) =>
bindableObject.SetValue(TappedCommandParameterProperty, value);
}
After that reference your behavior namespace in XAML and specify the property values using fully qualified names:
<ViewCell StyleId="disclosure-indicator"
behaviors:TappedCommandViewCell.TappedCommand="{Binding BrowseCommand}"
behaviors:TappedCommandViewCell.TappedCommandParameter="https://www.google.com">
<StackLayout Orientation="Horizontal">
<Label Text="Recipient"
VerticalOptions="Center"
Margin="20,0"/>
<Label Text="{Binding LedgerRecord.Recipient}"
HorizontalOptions="EndAndExpand"
VerticalOptions="Center"
Margin="0,0,20,0"/>
</Label>
</StackLayout>
</ViewCell>
The above will allow you to use MVVM and no Tap Gesture Recognizers.
The first problem is that you're mixing the code-behind and MVVM
approaches in the same code. It is confusing and certainly not the
right way to code what you want to achieve. So, all commanding must
be in the ViewModel attached to the View, no code-behind apart some
code only used for UI effects.
There is no need to define a gesture recognizer for all visual items since you just want to detect the tap on all the surface of the viewcell. To achieve this you must define all children of the ViewCell with InputTransparent=true. So the tap will not be detected and will be trapped by the parent ViewCell (you
must indicate the InpuTransparent because there is no tap event
bubbling in X.Forms).
Showing and Hidding the picker is a View problem not a ViewModel one. So here you can use some code-behind to create an event handler for the ViewCell Tapped event. This handler will just set visible=true on the picker.
The picker selected event must be connected to a corresponding Command in the ViewModel. So each time the picker is displayed and a value is selected your viewmodel will be aware of the action. This is the only command you need in your viewmodel. Depending of XForms version the picker has no bindable command, so you can use one of the numerous "bindablepicker" implementation you can find on the web or you can also use a XAML EventToCommand Behavior.
So there is two different problems : showing/hidding the picker which can be achieved directly in XAML or with the help of a bit of code-behind; and the picker item selection that must be managed using a Command in the viewmodel.
Hoping this will help you
I am trying to get to grips with effective use of the TopAppBar in Windows Store Apps. I have used the Basic Page template and added a NavigateCommand to the NavigationHelper class in the same way that the GoForwardCommand and GoBackCommand have been implemented. I have also added a constructor to the RelayCommand to enable Execute and CanExecute delegates to take an object parameter
public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_executeWithParam = execute;
_canExecuteWithParam = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? (_canExecuteWithParam == null ? true : _canExecuteWithParam(parameter)) : _canExecute();
}
public void Execute(object parameter)
{
if (_execute == null)
_executeWithParam(parameter);
else
_execute();
}
In my XAML for the MainPage I have the following code:
<Page
x:Name="pageRoot"
x:Class="UniAppTest.MainPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UniAppTest"
xmlns:common="using:UniAppTest.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
<x:String x:Key="AppName">Welcome to universal apps!</x:String>
</Page.Resources>
<Page.TopAppBar>
<AppBar>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<Button Content="Home" Width="140" Height="80" />
<Button Content="Summary" Width="140" Height="80"
Command="{Binding NavigateCommand}"
CommandParameter="SummaryPage" />
<Button Content="Reports" Width="140" Height="80"
Command="{Binding NavigationHelper.NavigateCommand, ElementName=pageRoot}"
CommandParameter="ReportsPage " />
</StackPanel>
<SearchBox Grid.Column="1" Width="300" Height="50" HorizontalAlignment="Right" />
</Grid>
</AppBar>
</Page.TopAppBar>
Neither of the Buttons invoke the command when pressed.
However, if I add a button to the main page content the command works successfully:
<Button x:Name="summaryButton" Margin="39,59,39,0"
Command="{Binding NavigationHelper.NavigateCommand, ElementName=pageRoot}"
CommandParameter="SummaryPage"
Grid.Row="1" Content="Summary"
Style="{StaticResource TextBlockButtonStyle}"
VerticalAlignment="Top"
FontSize="24"/>
Can anyone help me see what I'm doing wrong. I think it must be in the Binding reference. I aalways find this confusing. Would appreciate any help. Thanks.
Mmmm... As I know, you are not Binding Anything to the top.appbar or the parent, So when it tries to see were has to go to find the command he doesn't know where it is.
When you make it in a simple button the button has a parent with the Bind, isn't?
I too desire nice commands to do the navigation work. I came up with a strongly-type way of doing things. Works nicely from XAML, code-behind or viewmodel.
First, make a class that will contain as many commands as you have pages.
public class PagesLocator
{
private Dictionary<string, RelayCommand> commands = new Dictionary<string, RelayCommand>();
private Frame frame;
private bool useCurrentFrame;
public PagesLocator()
{
this.useCurrentFrame = true;
}
public PagesLocator(Frame frame)
{
this.frame = frame;
}
public RelayCommand Home
{
get { return this.GetCommand("Home", typeof(HomePage)); }
}
public RelayCommand Page2
{
get { return this.GetCommand("Page2", typeof(Page2)); }
}
private RelayCommand GetCommand(string key, Type typeOfPage)
{
if (this.commands.ContainsKey(key))
{
return this.commands[key];
}
var item = new RelayCommand(x => this.GetFrame().Navigate(typeOfPage, x));
this.commands.Add(key, item);
return item;
}
private Frame GetFrame()
{
if (this.frame != null)
{
return this.frame;
}
else if (this.useCurrentFrame)
{
return (Frame)Window.Current.Content;
}
else
{
throw new InvalidOperationException("Cannot navigate. Current frame is not set.");
}
}
}
Instantiate that in the app resources to have a data-bindable source.
<Application.Resources>
<common:PagesLocator x:Key="Navigator" />
</Application.Resources>
Finally, you can bind any command from this source.
<Button Content="go to page 2"
Command="{Binding Page2, Source={StaticResource Navigator}}"
CommandParameter="extra nav parameter here" />
<AppBarButton Label="page2" Command="{Binding Page2, Source={StaticResource Navigator}}" />
I have a Pivot element that has a header template and an itemtemplate with a listbox which also has a itemtemplate. The header template is bound to a list of "DOWS" which i create via code. This works fine. Each DOW has a entityset TDs and i want to bind the listbox itemtemplate to this source. Once i bound it, deleting an item updates the ui fine but adding an item doesn't update the ui.
the entityset is based off of the "Local database with mvvm" example here:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh286405(v=vs.105).aspx
I've researched for a few days and cant find anything helpful. some solutions i found where to wrap the entityset in a observable collection but that didnt seem to work. Another one was to use BindingLists, but entitySets dont have "ToBindingList()" for windows phone 7. Ive created observable collections in my ViewModel that i could bind to, but then i have no way of telling the listbox itemtemplate which collection to bind to when its created.
Any ideas?
I Can post more code if needed.
Thanks!!
Example Observablen Collections in ViewModel
private ObservableCollection<TDItem> _twoDaysAgoItems;
public ObservableCollection<TDItem> TwoDaysAgoItems
{
get { return _twoDaysAgoItems; }
set
{
_twoDaysAgoItems = value;
NotifyPropertyChanged("TwoDaysAgoItems");
}
}
private ObservableCollection<TDItem> _yesterdayItems;
public ObservableCollection<TDItem> YesterdayItems
{
get { return _yesterdayItems; }
set
{
_yesterdayItems = value;
NotifyPropertyChanged("YesterdayItems");
}
}
private ObservableCollection<TDItem> _todayItems;
public ObservableCollection<TDItem> TodayItems
{
get { return _todayItems; }
set
{
_todayItems = value;
NotifyPropertyChanged("TodayItems");
}
}
EntitySet
private EntitySet<TDItem> _tds;
[Association(Storage = "_ts", OtherKey = "_dowId", ThisKey = "Id")]
public EntitySet<TDItem> TDs
{
get { return this._tds;
}
set {
NotifyPropertyChanging("TDs");
this._tds.Assign(value);
NotifyPropertyChanged("TDs");
}
}
public DOW()
{
_tds = new EntitySet<TDItem>(
new Action<TDItem>(this.attach_TD),
new Action<TDItem>(this.detach_TD)
);
}
Pivot
<controls:Pivot x:Name="TDPivotDisplay" SelectedIndex="2" Margin="0,-10,0,0" Grid.Row="0" Title="TD" Foreground="White" FontWeight="light" VerticalAlignment="Top" FontSize="29.333" Style="{StaticResource PivotStyle1}" FontFamily="{StaticResource Akzidenz Grotesk}">
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="DOW" Foreground="{Binding Colour}" FontSize="110" FontFamily="{StaticResource Akzidenz Grotesk}" Text="{Binding Header}"/>
<TextBlock x:Name = "FullDate" Foreground="{Binding Colour}" FontWeight="light" FontSize="30" FontFamily="{StaticResource Akzidenz Grotesk}" HorizontalAlignment="center" Text="{Binding Date}"/>
</StackPanel>
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<Grid Height="421">
<ListBox ItemsSource = "{Binding TDs}" ItemTemplate = "{StaticResource ListboxItemTemp}" x:Name ="TDLists" Margin="12, 0, 12, 0" Width="440"/>
</Grid>
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
(Windows Phone 7 SDK)
Hi,
I have a ListBox named CTransactionList, and adding some items to this listbox by using data bindings. And Here I have a class to evaulate data bindings.(I think my listbox's XAML code is not needed here as my issue comes out due to some coding problems)
public class CTransaction
{
public String Date1 { get; set; }
public String Amount1 { get; set; }
public String Type1 { get; set; }
public CTransaction(String date1, String amount1, String type1)
{
this.Date1 = date1;
this.Amount1 = amount1;
switch (type1)
{
case "FR":
this.Type1 = "Images/a.png";
break;
case "TA":
this.Type1 = "Images/b.png";
break;
case "DA":
this.Type1 = "Images/c.png";
break;
}
}
}
Here I have a function, when a move completes, this function runs;(this function is supposed to add new items when function runs)
List<CTransaction> ctransactionList = new List<CTransaction>();//Define my list
public void movecompleted()
{
String DefaultDate = "";
String DefaultAmount = "";
String RandomType = "";
DefaultDate = nameend.Text;
DefaultAmount = diffend.Text;
RandomType = "FR";
ctransactionList.Add(new CTransaction(DefaultDate, DefaultAmount, RandomType));
CTransactionList.ItemsSource = ctransactionList;
}
For the first time when move completes, it adds the required elements to my list. But for next times, it does not add to my list. The old one keeps its existence. I tried also this format by getting list definition into my function like:
public void movecompleted()
{
List<CTransaction> ctransactionList = new List<CTransaction>(); //List definition in function
String DefaultDate = "";
//...Same
}
And this time, it replaces my current item with new one. Do not append at the end of list. (Both ways, I have one item in my list, not more) How can I do everytime append to list? Where am I wrong?
Here is my Debugging report. Both ctransactionList object and CTransactionList ListBox have the needed items according to my observations in debug watcher. Only problem, CTransactionList cant refresh itself properly even if it has the resources retrieved from ctransactionList object.
Here is my XAML code for my relevant listbox.(IF NEEDED)
<Grid>
<ListBox Name="CTransactionList" Margin="0,0,0,0" >
<ListBox.ItemTemplate >
<DataTemplate>
<Button Width="400" Height="120" >
<Button.Content >
<StackPanel Orientation="Horizontal" Height="80" Width="400">
<Image Source="{Binding Type1}" Width="80" Height="80"/>
<StackPanel Orientation="Vertical" Height="80">
<StackPanel Orientation="Horizontal" Height="40">
<TextBlock Width="100" FontSize="22" Text="Name:" Height="40"/>
<TextBlock Width="200" FontSize="22" Text="{Binding Date1}" Height="40"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="40">
<TextBlock Width="100" FontSize="22" Text="Difficulty:" Height="40"/>
<TextBlock Width="200" FontSize="22" Text="{Binding Amount1}" Height="40"/>
</StackPanel>
</StackPanel>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Thanks in advance.
As you rightly mentioned, it's not related to your XAML. Problem is in your code.
First simple fix may to clear the ItemsSource before setting the new source, like this
CTransactionList.ItemsSource = null;
CTransactionList.ItemsSource = ctransactionList;
This way, you are clearing the existing the databinding and enforcing the new list into the ListBox.
The other and suggestible fix is,
"Change your List to ObservableCollection. Because, ObservableCollection extends the INotifyPropertyChanged and hence has the ability to auto update the ListBox"
List<CTransaction> ctransactionList = new List<CTransaction>();//Change this to below
ObservableCollection<CTransaction> ctransactionList = new ObservableCollection<CTransaction>();//Define my collection
But a breakpoint before
CTransactionList.ItemsSource = ctransactionList;
And run the function twice. Do you have two items in ctransactionList now?
I suspect the binding fails and ctransactionList are in fact increasing