So I need to create a custom button, on what i have to create grid and on this grid I need to create several labels with specific informations.
This is code where i`m adding child to button
private void HighlightTodayDay()
{
Label label1 = new Label()
{
BackgroundColor = Color.DarkRed,
Text = "lbl1"
};
Label label2 = new Label()
{
BackgroundColor = Color.Gold,
Text = "lbl2"
};
if ((DateTime.Today.Year == actualVisibleMonth.Year) && (DateTime.Today.Month == actualVisibleMonth.Month))
{
foreach (var child in Children.Reverse())
{
if (child.ClassId.ToString() == ("actualDayButtonID" + DateTime.Today.Day.ToString()) && child.IsEnabled == true)
{
DayButton todayDayButton = dayButtonsList[DateTime.Today.Day + shiftOfFirstDay];
todayDayButton.TextColor = Color.FromHex("#0f0");
//upto this line everything is working as it should
todayDayButton.insideGrid.Children.Add(label1, 0, 0); //do nothing
todayDayButton.insideGrid.Children.Add(label2, 0, 1); //do nothing
return;
}
}
}
}
and here is code from "custom" button
class DayButton : Button
{
public string EventDate;
public string EventStartTime;
public string EventEndTime;
public string EventShift;
public string EventName;
public string EventDescription;
public Grid insideGrid;
public DayButton()
{
insideGrid = new Grid();
insideGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
insideGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(3, GridUnitType.Star) });
insideGrid.Parent = this;
}
}
It should look like this click to see image
you can add a GestureRecognizer to the Grid and then bind the tap event.
Ex of button code (now a ContentView):
class DayButton : ContentView
{
public string EventDate;
public string EventStartTime;
public string EventEndTime;
public string EventShift;
public string EventName;
public string EventDescription;
public Grid insideGrid;
public event EventHandler Clicked;
private TapGestureRecognizer _buttonTap;
private Lable _ButtonText;
public DayButton()
{
_ButtonText = new Lable
{
Text = EventName
}
insideGrid = new Grid
{
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
RowSpacing = 0,
RowDefinitions =
{
new RowDefinition {Height = GridLength.Auto} //0
},
ColumnDefinitions =
{
new ColumnDefinition {Width = GridLength.Star} //0
}
};
//Add your elements to the grid
insideGrid.Children.Add(_ButtonText, 0, 1, 0, 1)
//Set the grid as the content of this view
Content = insideGrid;
_buttonTap = new TapGestureRecognizer();
this.GestureRecognizers.Add(_buttonTap);
_buttonTap.Tapped += ButtonClicked;
}
}
private async void ButtonClicked(object sender, EventArgs e)
{
if (this.IsEnabled)
{
Clicked?.Invoke(this, e);
}
}
Then you can bind the "Clicked" event where you implement the button.
private DayButton _btn1 = new DayButton(){ EventName = "FooBaar"};
protected override void OnAppearing()
{
_btn1.Clicked += OnDayBtnClicked;
base.OnAppearing();
}
protected override void OnDisappearing()
{
_btn1.Clicked -= OnDayBtnClicked;
base.OnDisappearing();
}
private void OnDayBtnClicked(object sender, EventArgs e)
{
//What to do when a button is clicked
}
I decided to dismiss button and change it to stack layout (sick!) and to this stacklayout i`m adding new label with events!
soo code look like this:
public partial class Calendar : Grid
{...
public delegate void OnDayClickedDelegate(DateTime dateOfClickedDay);
public event OnDayClickedDelegate OnDayClicked;
...
private void DayClick(DateTime clickedDate)
{
OnDayClicked(clickedDate);
}
...
private void SomeVoid()
{...
DayLayout eventInDay = dayLayoutList[dayID];
var eventLabel = new Label
{
BackgroundColor = color,
Text = name.ToUpper(),
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
FontAttributes = FontAttributes.Bold
};
eventInDay.Children.Add(eventLabel);
...}
}
and day view
private class DayLayout : StackLayout
{
public delegate void OnClickedDelegate(DateTime dateOfClickedDay);
public event OnClickedDelegate OnClicked;
public Label DayNumber;
public DayLayout(DateTime day)
{
GestureRecognizers.Add
(
new TapGestureRecognizer
{
Command = new Command(() => OnClicked(day))
}
);
var dayNumber = new Label
{
HorizontalTextAlignment = TextAlignment.End,
VerticalTextAlignment = TextAlignment.Start,
Text = day.ToString("dd"),
FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)),
FontAttributes = FontAttributes.Bold
};
DayNumber = dayNumber;
this.Children.Add(DayNumber);
}
}
Related
I am using WPF Live Charts Library. I am trying to create a bar chart generically.
Following is my code. Can't do it in XAML as it doesn't support generics.
public abstract class AbstractGenericBarChart<T> : UserControl, INotifyPropertyChanged
{
SeriesCollection _SeriesCollection;
public SeriesCollection SeriesCollection { get { return _SeriesCollection; } set { _SeriesCollection = value; notifyPropertyChanged("SeriesCollection"); } }
string[] _Labels;
public string[] Labels { get { return _Labels; } set { _Labels = value; notifyPropertyChanged("Labels"); } }
Func<int, string> _Formatter;
public Func<int, string> Formatter { get { return _Formatter; } set { _Formatter = value; notifyPropertyChanged("Formatter"); } }
public abstract void constructChart(List<T> chartItems);
public void init(string xLabel, string yLabel)
{
renderChart(xLabel, yLabel);
}
public void renderChart(string xLabel, string yLabel)
{
CartesianChart chart = new CartesianChart { Margin = new Thickness(10, 10, 10, 10), LegendLocation = LegendLocation.Bottom, DataTooltip = new DefaultTooltip { SelectionMode = TooltipSelectionMode.SharedYValues } };
Axis xAxis = new Axis { Foreground = Brushes.Black, FontSize = 14d, Title = xLabel };
Axis yAxis = new Axis { Foreground = Brushes.Black, FontSize = 14d, Title = yLabel };
chart.AxisX.Add(xAxis);
chart.AxisY.Add(yAxis);
setBinding("LabelFormatter", Formatter, xAxis, Axis.LabelFormatterProperty);
setBinding("Labels", Labels, yAxis, Axis.LabelsProperty);
setBinding("Series", SeriesCollection, chart, CartesianChart.SeriesProperty);
Content = chart;
}
public void setBinding(string propertyName, object source, FrameworkElement control, DependencyProperty dependencyProperty)
{
Binding binding = new Binding(propertyName)
{
Source = source
};
control.SetBinding(dependencyProperty, binding);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void notifyPropertyChanged(string prop)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
}
internal class BarChart : AbstractGenericBarChart<TopTransactingCount>
{
public override void constructChart(List<TopTransactingCount> chartItems)
{
SeriesCollection = new SeriesCollection
{
new RowSeries
{
Title = "Transaction Count",
Values = new ChartValues<long>(chartItems.Select(x=>x.TransCount))
}
};
Labels = chartItems.Select(x => x.Date.ToShortDateString()).ToArray();
Formatter = value => value.ToString();
DataContext = this;
}
}
At startup I see an empty chart control which is expected.
I call constructChart method on submit button click.
public partial class TotalTransCountsChart : UserControl, IChart
{
private BarChart chart = new BarChart();
List<object> chartData;
public TotalTransCountsChart()
{
InitializeComponent();
}
public void init(List<object> chartData)
{
this.chartData = chartData;
chart.init("Transaction Count", "Date");
chart.constructChart(chartData.Cast<TopTransactingCount>().ToList());
grid.Children.Add(chart);
Grid.SetRow(chart, 3);
}
private void CmdSubmit_Click(object sender, System.Windows.RoutedEventArgs e)
{
chart.constructChart(chartData.Cast<TopTransactingCount>().ToList());
}
}
However, the chart still remains empty. I think the binding part in the code is not working as expected. I am stuck at this point.
it looks like you are creating Bindings incorrectly (try to confirm it from Visual Studio Output window - it reports messages about incorrect bindings).
for example:
setBinding("Labels", Labels, yAxis, Axis.LabelsProperty);
public void setBinding(string propertyName, object source, FrameworkElement control, DependencyProperty dependencyProperty)
{
Binding binding = new Binding(propertyName)
{
Source = source
};
control.SetBinding(dependencyProperty, binding);
}
Labels is a string[], and you have a binding , which attempts to use "Labels" property - which doesn't exist.
you need a valid binding source, most likely DataContext:
setBinding("LabelFormatter", DataContext, xAxis, Axis.LabelFormatterProperty);
setBinding("Labels", DataContext, yAxis, Axis.LabelsProperty);
setBinding("Series", DataContext, chart, CartesianChart.SeriesProperty);
or better yet - don't specify source and all bindings will connect to current DataContext, even if it updates:
public void setBinding(string propertyName, object source, FrameworkElement control, DependencyProperty dependencyProperty)
{
Binding binding = new Binding(propertyName);
control.SetBinding(dependencyProperty, binding);
}
how can two different items in a list be bound to one another hence when one is deleted its bound patner is also deleted.The question may sound simple, but the items are in two different lists.
public class MyClass{
public StackLayout SavedHoursLayout = new StackLayout {};
public Label RemoveHoursLabel;
public TapGestureRecognizer RemoveTapped;
public Grid HoursRemoveGrid;
public Button AddHoursButton = new Button();
public Label Correct = new Label{Text="Correct"};
public list<Label> ItemsLayout = new list<Label>();
public MyClass()
{
Content = new StackLayout
{
Children = { AddHoursButton,SavedHoursLayout }
}
AddHoursButton.Clicked+=AddHoursButton_Clicked;
}
public void AddSavedHours()
{
Label Time = new Label { };
RemoveHoursLabel = new Label {
Text="remove",TextColor=Color.Red,FontAttributes=FontAttributes.Italic};
HoursRemoveGrid = new Grid();
RemoveTapped = new TapGestureRecognizer();
this.BindingContext = HoursRemoveGrid;
HoursRemoveGrid.Children.Add(Time,0,0);
HoursRemoveGrid.Children.Add(RemoveHoursLabel,1,0);
SavedHoursLayout.Children.Add(HoursRemoveGrid);
RemoveHoursLabel.GestureRecognizers.Add(RemoveTapped);
RemoveTapped.Tapped += RemoveTapped_Tapped;
ItemsLayout.Children.Add(Correct);
void RemoveTapped_Tapped(object sender, EventArgs e)
{
var grid = (sender as Label).Parent as Grid;
int position = SavedHoursLayout.Children.IndexOf(grid);
SavedHoursLayout.Children.RemoveAt(position);
}
}
private void AddHoursButton_Clicked(object sender, System.EventArgs e)
{
AddSavedHours();
}
}
Question
Now when i click RemoveHourLabel, i want to remove the Label Correctin ItemsLayoutcorresponding to the RemovehoursGrid.
NB
There are already a number of Labels in ItemsLayout, so each Label Correct does not have the same index as that of its correspondent RemoveHoursGrid.
Solution:
You can create a new list<Label> to hold the labels so that it will have the same index as that of its correspondent RemoveHoursGrid.
First, create a new list, let's call it tempItemsLayout :
public List<Label> tempItemsLayout = new List<Label>();
Then in your method AddSavedHours, Add the correct to tempItemsLayout too:
public void AddSavedHours()
{
//...other codes
RemoveHoursLabel.GestureRecognizers.Add(RemoveTapped);
RemoveTapped.Tapped += RemoveTapped_Tapped;
ItemsLayout.Add(Correct);
//Add the correct to tempItemsLayout too
tempItemsLayout.Add(Correct);
//...other codes
}
Then in your RemoveTapped_Tapped, Remove the label from both tempItemsLayout and ItemsLayout:
void RemoveTapped_Tapped(object sender, EventArgs e)
{
var grid = (sender as Label).Parent as Grid;
int position = SavedHoursLayout.Children.IndexOf(grid);
SavedHoursLayout.Children.RemoveAt(position);
Label tempLabel = tempItemsLayout[position];
//Remove the label from both tempItemsLayout and ItemsLayout
tempItemsLayout.Remove(tempLabel);
ItemsLayout.Remove(tempLabel);
}
Try and let me know if it works.
I have listview that have two views manipulated dynamically label and button, and I am trying to access button click to go to the details page on button click.
below is my custom ViewCell
protected override async void OnAppearing()
{
listClass.ItemsSource = list;
listClass.ItemTemplate = new DataTemplate(typeof(ItemTemplateViewCell ));
}
public class ItemTemplateViewCell : ViewCell
{
Label NameLbl = new Label();
StackLayout sLayout = new StackLayout ();
Button btnViewcell = new Button {Text = "Show class details"};
public ItemTemplateViewCell()
{
NameLbl.SetBinding(Label.TextProperty, "Name");
sLayout.Children.Add(NameLbl);
btnViewcell.Clicked += (s, e) =>
{
// Navigation.PushAsync(new Home()); //I can not using this line
// does not exist in the current context, why cant i navigate to
// another page from inside datatemplate in List view
};
sLayout.Children.Add(btnViewcell);
this.View = sLayout;
}
}
You can pass the Navication to ViewCell through constructor:
public class ItemTemplateViewCell : ViewCell
{
// Navigation Mermber
INavigation MyNavigation;
Label NameLbl = new Label();
StackLayout sLayout = new StackLayout ();
Button btnViewcell = new Button {Text = "Show class details"};
public ItemTemplateViewCell(INavigation navigation)
{
MyNavigation = navigation;
NameLbl.SetBinding(Label.TextProperty, "Name");
sLayout.Children.Add(NameLbl);
btnViewcell.Clicked += ButtonShowDetails_Clicked;
sLayout.Children.Add(btnViewcell);
this.View = sLayout;
}
private void ButtonShowDetails_Clicked(object sender, EventArgs e)
{
MyNavigation.PushAsync(new Home());
}
}
Then pass the Navication through the delegate Function
protected override async void OnAppearing()
{
listClass.ItemsSource = list;
listClass.ItemTemplate = new DataTemplate(Function) ;
}
public object Function()
{
return new ItemTemplateViewCell (Navigation);
}
Then you can access the Navigation object in ViewCell
Simply you are able to use CommandParameterProperty with binding :
Example:
ListViewClass.ItemTemplate = new DataTemplate(() =>
{
var GoHomeButton = new Button { Text = "Go Home", HorizontalOptions = LayoutOptions.StartAndExpand };
GoHomeButton.SetBinding(Button.CommandParameterProperty, new Binding("Name"));
GoHomeButton.Clicked += Gohome;
//return new view cell
}
private void Gohome(object sender, EventArgs e)
{
Navigation.PushAsync(new Home());
}
For more info check the following Link:
http://www.c-sharpcorner.com/blogs/handling-child-control-event-in-listview-using-xamarinforms1
What I think is going wrong is that you are performing an action immediately in the initialization of the class. You should split it up so like below. Another issue is that you do initialization of variables outside of the methods. This might go okay, but I prefer the below code:
public class ItemTemplateViewCell : ViewCell
{
Label nameLbl;
StackLayout sLayout;
Button btnViewcell;
public ItemTemplateViewCell()
{
nameLbl = new Label()
sLayout = new StackLayout ()
btnViewcell = new Button {Text = "Show class details"};
NameLbl.SetBinding(Label.TextProperty, "Name");
sLayout.Children.Add(NameLbl);
btnViewcell.Clicked += OnButtonClicked;
sLayout.Children.Add(btnViewcell);
this.View = sLayout;
}
void OnButtonClicked(object sender, EventArgs e)
{
Navigation.PushAsync(new Home());
}
}
I think this should work in your case but I can't be sure. I don't think what you posted is one on one your code since I don't see any initialization of s and e in your code and as mentioned in the comments the comment in your code would cause issues if you really put it as in the question. Also you don't share the code of the Home class. Something might be wrong at that end.
Navigation is not available inside of a ViewCell, this means you can't access it right from your ViewCell. But this should work:
App.Current.MainPage.Navigation.PushAsync(new Home());
The whole code:
protected override async void OnAppearing()
{
listClass.ItemsSource = list;
listClass.ItemTemplate = new DataTemplate(typeof(ItemTemplateViewCell ));
}
public class ItemTemplateViewCell : ViewCell
{
Label NameLbl = new Label();
StackLayout sLayout = new StackLayout ();
Button btnViewcell = new Button {Text = "Show class details"};
public ItemTemplateViewCell()
{
NameLbl.SetBinding(Label.TextProperty, "Name");
sLayout.Children.Add(NameLbl);
btnViewcell.Clicked += (s, e) =>
{
App.Current.MainPage.Navigation.PushAsync(new Home());
};
sLayout.Children.Add(btnViewcell);
this.View = sLayout;
}
}
I want to bind a border generated dynamically from code behind.
below is my model that I bind with the border.
public class MapTextboxGridModel : INotifyPropertyChanged
{
private MaptextBoxGridStylePropertiesModel _GridStyleProperties = new MaptextBoxGridStylePropertiesModel();
public MaptextBoxGridStylePropertiesModel GridStyleProperties
{
get { return _GridStyleProperties; }
set
{
_GridStyleProperties = value;
OnPropertyChanged("GridStyleProperties");
}
}
}
My style for each cells is in the _GridStyleProperties. And in _GridStyleProperties model I have one property "_Name" as below.
public class MaptextBoxGridStylePropertiesModel : INotifyPropertyChanged
{
private string _Name = "Enter your text";
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged("Name");
}
}}
// following border(multiple, so I will have border in each cell of the grid) is created inside a grid
MapTextboxGridModel cellcontext = new MapTextboxGridModel();
Border db = new Border();
db.MouseLeftButtonDown += db_MouseLeftButtonDown;
db.DataContext = cellcontext;
TextBlock block = new TextBlock() { Text = cellcontext.GridStyleProperties.Name };
and then when I click on any of the cell in the grid.
void db_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (columnpossition == -1 && rowpossition == -1)
{
columnpossition = Grid.GetColumn(sender as Border);
rowpossition = Grid.GetRow(sender as Border);
}
else
{
Border bod = sender as Border;
Grid grd = bod.Parent as Grid;
int col = Grid.GetColumn(bod);
int row = Grid.GetRow(bod);
if (col == columnpossition && row == rowpossition)
{
}
else
{
TextBlock dbtxt = bod.Child as TextBlock;
imodel.GridStyleProperties.needtoshow = true;
Binding textbnd = new Binding();
textbnd.Source = bod.DataContext as MapTextboxGridModel;
textbnd.Path = new PropertyPath("StyleProperties.Name"); // Is this possible
BindingOperations.SetBinding(dbtxt, TextBlock.TextProperty, textbnd);
columnpossition = col;
rowpossition = row;
}
}
}
I can't understand where am I making mistake. Please suggest me what change should be done in above code.
I have found this : How to show a loading graphic/animation when wpf data binding is taking place
But don't understand how to apply it for my work.
I have My MainWindow. It call all my user controls in it.
On a user control, I have a DataGrid. after press "Go" button, the datagrid load data from MySQL. It take a long time to do and I want to show a dialog window with "Please Wait" during the loading of the datagrig.
I have found the link below but don't understant how to call it correctly.
Do I need to put this "loader" in a new class file like "Loader.cs" andthe button call it ? Ok but how to close it when datagrid is finished ?
I'm lost... Well if an other solution exist and simply to use...
Thanks by advance
EDIT TEST 1 :
Tried an simple test with slider to get a time to wait and a button.
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace TEST_LoadingPage
{
/// <summary>
/// Logique d'interaction pour MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnTester_Click(object sender, RoutedEventArgs e)
{
Window waitWindow = new Window { Height = 100, Width = 200, WindowStartupLocation = WindowStartupLocation.CenterScreen, WindowStyle = WindowStyle.None };
waitWindow.Content = new TextBlock { Text = "Veuillez patienter...", FontSize = 30, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center };
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate
{
Dispatcher.BeginInvoke(new Action(delegate { waitWindow.ShowDialog(); }));
lbReussite.Visibility = Loop.Pause(slider.Value);
Dispatcher.BeginInvoke(new Action(delegate() { waitWindow.Close(); }));
};
worker.RunWorkerAsync();
}
}
public class Loop
{
public static System.Windows.Visibility Pause(double duree)
{
try
{
DateTime begin = new DateTime();
DateTime end = new DateTime();
int i = 0;
begin = DateTime.Now;
end = DateTime.Now.AddSeconds(duree);
while (DateTime.Now <= end)
i++;
return System.Windows.Visibility.Visible;
}
catch (Exception)
{
return System.Windows.Visibility.Hidden;
}
}
}
}
but don't work with error :
The calling thread can not access this object because a different thread owns it
I know its a courant error but I don't see "DispatcherTimer" or else that I've seen before in precedent project... So I'll try the second code tomorrow BUT. I don't understand where i put my method :(
EDIT 2
I tried with your code... I'm too stupide maybe.
I've write the class in a Loader.cs and in my MainWiondow (its a test)
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnTester_Click(object sender, RoutedEventArgs e)
{
Loader<List<Donnees>> loader = new Loader<List<Donnees>>(GenerateList((int)slider.Value);
loader.JobFinished += new Loader<Donnees>.OnJobFinished(loader_JobFinished);
loader.Load();
}
private List<Donnees> GenerateList(int number)
{
List<Donnees> list = new List<Donnees>();
for (int i = 1; i <= number; i++)
{
Donnees data = new Donnees();
data.Id = i;
data.Name = "Ligne " + i;
list.Add(data);
}
return list;
}
void loader_JobFinished(object sender, List<Donnees> result)
{
result = GenerateList((int)slider.Value);
dgDataGrid.ItemsSource = result;
}
}
public class Donnees
{
#region Properties
private int id;
public int Id
{
get { return id; }
set { id = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
#endregion
public Donnees()
{
id = -1;
name = "";
}
}
You put the following code in a method in the code-behind of your DataGrid-UserControl which gets called in your button-click-eventhandler:
Window waitWindow = new Window { Height = 100, Width = 200, WindowStartupLocation = WindowStartupLocation.CenterScreen, WindowStyle = WindowStyle.None };
waitWindow.Content = new TextBlock { Text = "Please Wait", FontSize = 30, FontWeight = FontWeights.Bold, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center };
Now you can decide...
...if you want to create a DataLoader-class, which loads the data and fires an DataLoaded event when completed, than add:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate
{
Dispatcher.BeginInvoke(new Action(delegate { waitWindow.ShowDialog(); }));
DataLoader dataLoader = new DataLoader();
dataLoader.DataLoaded += delegate
{
Dispatcher.BeginInvoke(new Action(delegate() { waitWindow.Close(); }));
};
dataLoader.LoadData();
};
worker.RunWorkerAsync();
... or if you just copy your data-loading-code into this method and add:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate
{
Dispatcher.BeginInvoke(new Action(delegate { waitWindow.ShowDialog(); }));
//do dataloading here
Dispatcher.BeginInvoke(new Action(delegate() { waitWindow.Close(); }));
};
worker.RunWorkerAsync();
EDIT: I wrote a class, which should do what you want without much code in the code-behind:
public class Loader<TFuncResult,TFirstArgType>:FrameworkElement
{
private Func<TFirstArgType,TFuncResult> _execute;
public TFuncResult Result { get; private set; }
public delegate void OnJobFinished(object sender, TFuncResult result);
public event OnJobFinished JobFinished;
public Loader(Func<TFirstArgType,TFuncResult> execute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
}
private Window GetWaitWindow()
{
Window waitWindow = new Window { Height = 100, Width = 200, WindowStartupLocation = WindowStartupLocation.CenterScreen, WindowStyle = WindowStyle.None };
waitWindow.Content = new TextBlock { Text = "Please Wait", FontSize = 30, FontWeight = FontWeights.Bold, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center };
return waitWindow;
}
public void Load(TFirstArgType firstarg, Window waitWindow = null)
{
if (waitWindow == null)
{
waitWindow = GetWaitWindow();
}
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate
{
Dispatcher.BeginInvoke(new Action(delegate { waitWindow.ShowDialog(); }));
Result = _execute(firstarg);
Dispatcher.BeginInvoke(new Action(delegate() { waitWindow.Close(); }));
};
worker.RunWorkerCompleted += delegate
{
worker.Dispose();
if (JobFinished != null)
{
JobFinished(this, Result);
}
};
worker.RunWorkerAsync();
}
}
EDIT 2: How to use it:
Lets say your GenerateList() returns Data of Type List<Donnees> and the arguments Type is of Type int (works with all Types):
Place this where you want to load the Data (e.g. in your Window_Loaded-Event):
Loader<List<Donnees>, int> loader = new Loader<List<Donnees>, int>(GenerateList);
loader.JobFinished += new Loader<List<Donnees>, int>.OnJobFinished(loader_JobFinished);
loader.Load((int)slider.Value);
Now call this EventHandler in the Code-Behind:
void loader_JobFinished(object sender, List<Donnees> result)
{
YourDataGrid.DataSource = result
}