I am creating a WPF Application implementing trial period by using this library Application Trial Maker this library writing Registration data on SystemFile but when I implement it in my project, it shows the registration dialog on every application run.
What I want is to show registration Dialog only in 2 scenarios:
1- first Run: after the user setup my application. I found these 2 questions check first run and show message and show dialog on first start of application the answers in both are using the Application.Setting and add a bool variable there, but in my case I want to make use of my Trial Maker library also I can't use Setting.Default[] inside my main because it is non-static and am not calling specific view model. I am just calling App.Run as you will see below.
2- when trial period or runs expired.
Here is My App.xaml.cs class :
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using SoftwareLocker;
using System.Globalization;
using System.Threading;
namespace PharmacyManagementSystem
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
public static void Main()
{
CultureInfo ci = CultureInfo.CreateSpecificCulture(CultureInfo.CurrentCulture.Name);
ci.DateTimeFormat.ShortDatePattern = "yyyy-MM-dd";
ci.DateTimeFormat.LongTimePattern = "HH:mm:ss";
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = ci;
TrialMaker t = new TrialMaker("Pharmacy Management System",
System.AppDomain.CurrentDomain.BaseDirectory + "\\RegFile.reg",
Environment.GetFolderPath(Environment.SpecialFolder.System) +
"\\TMSetp.dbf",
"Mobile: +249 914 837664",
15, 1000, "745");
byte[] MyOwnKey = { 97, 250, 1, 5, 84, 21, 7, 63,
4, 54, 87, 56, 123, 10, 3, 62,
7, 9, 20, 36, 37, 21, 101, 57};
t.TripleDESKey = MyOwnKey;
bool is_trial;
TrialMaker.RunTypes RT = t.ShowDialog();
if (RT != TrialMaker.RunTypes.Expired)
{
if (RT == TrialMaker.RunTypes.Full)
is_trial = false;
else
is_trial = true;
PharmacyManagementSystem.App app = new PharmacyManagementSystem.App();
app.InitializeComponent();
/// as i said am just calling App.Run
app.Run();
}
}
}
}
and here is TrialMaker.cs :
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
using System.IO;
using Microsoft.VisualBasic;
using System.Windows.Forms;
namespace SoftwareLocker
{
// Activate Property
public class TrialMaker
{
#region -> Private Variables
private string _BaseString;
private string _Password;
private string _SoftName;
private string _RegFilePath;
private string _HideFilePath;
private int _DefDays;
private int _Runed;
private string _Text;
private string _Identifier;
#endregion
#region -> Constructor
/// <summary>
/// Make new TrialMaker class to make software trial
/// </summary>
/// <param name="SoftwareName">Name of software to make trial</param>
/// <param name="RegFilePath">File path to save password(enrypted)</param>
/// <param name="HideFilePath">file path for saving hidden information</param>
/// <param name="Text">A text for contacting to you</param>
/// <param name="TrialDays">Default period days</param>
/// <param name="TrialRunTimes">How many times user can run as trial</param>
/// <param name="Identifier">3 Digit string as your identifier to make password</param>
public TrialMaker(string SoftwareName,
string RegFilePath, string HideFilePath,
string Text, int TrialDays, int TrialRunTimes,
string Identifier)
{
_SoftName = SoftwareName;
_Identifier = Identifier;
SetDefaults();
_DefDays = TrialDays;
_Runed = TrialRunTimes;
_RegFilePath = RegFilePath;
_HideFilePath = HideFilePath;
_Text = Text;
}
private void SetDefaults()
{
SystemInfo.UseBaseBoardManufacturer = false;
SystemInfo.UseBaseBoardProduct = true;
SystemInfo.UseBiosManufacturer = false;
SystemInfo.UseBiosVersion = true;
SystemInfo.UseDiskDriveSignature = true;
SystemInfo.UsePhysicalMediaSerialNumber = false;
SystemInfo.UseProcessorID = true;
SystemInfo.UseVideoControllerCaption = false;
SystemInfo.UseWindowsSerialNumber = false;
MakeBaseString();
MakePassword();
}
#endregion
// Make base string (Computer ID)
private void MakeBaseString()
{
_BaseString = Encryption.Boring(Encryption.InverseByBase(SystemInfo.GetSystemInfo(_SoftName), 10));
}
private void MakePassword()
{
_Password = Encryption.MakePassword(_BaseString, _Identifier);
}
/// <summary>
/// Show registering dialog to user
/// </summary>
/// <returns>Type of running</returns>
public RunTypes ShowDialog()
{
// check if registered before
if (CheckRegister() == true)
return RunTypes.Full;
frmDialog PassDialog = new frmDialog(_BaseString, _Password, DaysToEnd(), _Runed, _Text);
MakeHideFile();
DialogResult DR = PassDialog.ShowDialog();
if (DR == System.Windows.Forms.DialogResult.OK)
{
MakeRegFile();
return RunTypes.Full;
}
else if (DR == DialogResult.Retry)
return RunTypes.Trial;
else
return RunTypes.Expired;
}
// save password to Registration file for next time usage
private void MakeRegFile()
{
FileReadWrite.WriteFile(_RegFilePath, _Password);
}
// Control Registeration file for password
// if password saved correctly return true else false
private bool CheckRegister()
{
string Password = FileReadWrite.ReadFile(_RegFilePath);
if (_Password == Password)
return true;
else
return false;
}
// from hidden file
// indicate how many days can user use program
// if the file does not exists, make it
private int DaysToEnd()
{
FileInfo hf = new FileInfo(_HideFilePath);
if (hf.Exists == false)
{
MakeHideFile();
return _DefDays;
}
return CheckHideFile();
}
// store hidden information to hidden file
// Date,DaysToEnd,HowManyTimesRuned,BaseString(ComputerID)
private void MakeHideFile()
{
string HideInfo;
HideInfo = DateTime.Now.Ticks + ";";
HideInfo += _DefDays + ";" + _Runed + ";" + _BaseString;
FileReadWrite.WriteFile(_HideFilePath, HideInfo);
}
// Get Data from hidden file if exists
private int CheckHideFile()
{
string[] HideInfo;
HideInfo = FileReadWrite.ReadFile(_HideFilePath).Split(';');
long DiffDays;
int DaysToEnd;
if (_BaseString == HideInfo[3])
{
DaysToEnd = Convert.ToInt32(HideInfo[1]);
if (DaysToEnd <= 0)
{
_Runed = 0;
_DefDays = 0;
return 0;
}
DateTime dt = new DateTime(Convert.ToInt64(HideInfo[0]));
DiffDays = DateAndTime.DateDiff(DateInterval.Day,
dt.Date, DateTime.Now.Date,
FirstDayOfWeek.Saturday,
FirstWeekOfYear.FirstFullWeek);
DaysToEnd = Convert.ToInt32(HideInfo[1]);
_Runed = Convert.ToInt32(HideInfo[2]);
_Runed -= 1;
DiffDays = Math.Abs(DiffDays);
_DefDays = DaysToEnd - Convert.ToInt32(DiffDays);
}
return _DefDays;
}
public enum RunTypes
{
Trial = 0,
Full,
Expired,
UnKnown
}
#region -> Properties
/// <summary>
/// Indicate File path for storing password
/// </summary>
public string RegFilePath
{
get
{
return _RegFilePath;
}
set
{
_RegFilePath = value;
}
}
/// <summary>
/// Indicate file path for storing hidden information
/// </summary>
public string HideFilePath
{
get
{
return _HideFilePath;
}
set
{
_HideFilePath = value;
}
}
/// <summary>
/// Get default number of days for trial period
/// </summary>
public int TrialPeriodDays
{
get
{
return _DefDays;
}
}
/// <summary>
/// Get default number of runs for trial period
/// i modified here by adding this getter
/// </summary>
public int TrialPeriodRuns
{
get
{
return _Runed;
}
}
/// <summary>
/// Get or Set TripleDES key for encrypting files to save
/// </summary>
public byte[] TripleDESKey
{
get
{
return FileReadWrite.key;
}
set
{
FileReadWrite.key = value;
}
}
#endregion
#region -> Usage Properties
public bool UseProcessorID
{
get
{
return SystemInfo.UseProcessorID;
}
set
{
SystemInfo.UseProcessorID = value;
}
}
public bool UseBaseBoardProduct
{
get
{
return SystemInfo.UseBaseBoardProduct;
}
set
{
SystemInfo.UseBaseBoardProduct = value;
}
}
public bool UseBaseBoardManufacturer
{
get
{
return SystemInfo.UseBiosManufacturer;
}
set
{
SystemInfo.UseBiosManufacturer = value;
}
}
public bool UseDiskDriveSignature
{
get
{
return SystemInfo.UseDiskDriveSignature;
}
set
{
SystemInfo.UseDiskDriveSignature = value;
}
}
public bool UseVideoControllerCaption
{
get
{
return SystemInfo.UseVideoControllerCaption;
}
set
{
SystemInfo.UseVideoControllerCaption = value;
}
}
public bool UsePhysicalMediaSerialNumber
{
get
{
return SystemInfo.UsePhysicalMediaSerialNumber;
}
set
{
SystemInfo.UsePhysicalMediaSerialNumber = value;
}
}
public bool UseBiosVersion
{
get
{
return SystemInfo.UseBiosVersion;
}
set
{
SystemInfo.UseBiosVersion = value;
}
}
public bool UseBiosManufacturer
{
get
{
return SystemInfo.UseBiosManufacturer;
}
set
{
SystemInfo.UseBiosManufacturer = value;
}
}
public bool UseWindowsSerialNumber
{
get
{
return SystemInfo.UseWindowsSerialNumber;
}
set
{
SystemInfo.UseWindowsSerialNumber = value;
}
}
#endregion
}
}
I have added the getter for TrialPeriodRuns to make use of it.
In other scenarios I want my application Run directly without the Dialog for Registering. Other scenarios are when it is full version or when it is un-expired trial not running for first time.
Any ideas how I can achieve this ??
I recommend you to write the necessary data in the Windows Registry.
You can use this reference: https://msdn.microsoft.com/en-us/library/h5e7chcf.aspx
Thanks to the above discussion with #Akram Mashni. I come up with this Solution which work fine for my scenarios.
I modified the DaysToEnd() Method to public so i can call it with instance of the TrialMaker class from anywhere else (My Main() for example):
public int DaysToEnd()
{
FileInfo hf = new FileInfo(_HideFilePath);
if (hf.Exists == false)
{
MakeHideFile();
return _DefDays;
}
return CheckHideFile();
}
Then I make use of it in my Main() method to check my scenarios. When I call DaysToEnd() it will update the info stored on the SystemFile by calling CheckHideFile() inside it.
I called DaysToEnd() first so i can update the info in the SystemFile
DaysToEnd() will return int value representing days remain in trial period. Also I called get for TrialPeriodRuns which I added earlier to the library and it represent the remaining runs in the trial period.
Also I implemented nested if-else statements to check my scenarios:
int daystoend = t.DaysToEnd();
int trialperiodruns = t.TrialPeriodRuns;
/// Check if it is first run here
if (dte == 15 && tpr == 1000)
{
bool is_trial;
/// then show the Registration dialog
TrialMaker.RunTypes RT = t.ShowDialog();
if (RT != TrialMaker.RunTypes.Expired)
{
if (RT == TrialMaker.RunTypes.Full)
is_trial = false;
else
is_trial = true;
PharmacyManagementSystem.App app = new PharmacyManagementSystem.App();
app.InitializeComponent();
app.Run();
}
}
/// Check if it is trial but not first run
/// no Registration Dialog will show in this case
else if (dte > 0 && tpr > 0)
{
PharmacyManagementSystem.App app = new PharmacyManagementSystem.App();
app.InitializeComponent();
app.Run();
}
/// Check if it is expired trial
else if (dte == 0 || tpr == 0)
{
bool is_trial;
/// then show the Registration Dialog here
TrialMaker.RunTypes RT = t.ShowDialog();
if (RT != TrialMaker.RunTypes.Expired)
{
if (RT == TrialMaker.RunTypes.Full)
is_trial = false;
else
is_trial = true;
PharmacyManagementSystem.App app = new PharmacyManagementSystem.App();
app.InitializeComponent();
app.Run();
}
}
/// the full version scenario remain and it comes here
/// no need to show Registration Dialog
else
{
bool is_trial;
TrialMaker.RunTypes RT = t.ShowDialog();
if (RT != TrialMaker.RunTypes.Expired)
{
if (RT == TrialMaker.RunTypes.Full)
is_trial = false;
else
is_trial = true;
PharmacyManagementSystem.App app = new PharmacyManagementSystem.App();
app.InitializeComponent();
app.Run();
}
}
And finally it works like a charm for me
thanks again #Akram Mashni for inspiring me
Related
I am following James Montemagno's tutorial to add pull-to-refresh support for my Layouts, it works perfect on Android but iOS generates the error below when I navigate to the same page as Android does.
System.InvalidCastException: < Timeout exceeded getting exception details >
The page I am trying to display is a simple StackLayout, which again works perfectly on Android.
This is my iOS renderer class from the tutorial
[assembly: ExportRenderer(typeof(RefreshableLayout), typeof(RefreshableLayoutiOS))]
namespace SocialNetwork.iOS.Renderers
{
[Preserve(AllMembers = true)]
public class RefreshableLayoutiOS : ViewRenderer<RefreshableLayout, UIView>
{
public async static void Init()
{
var temp = DateTime.Now;
}
UIRefreshControl refreshControl;
protected override void OnElementChanged(ElementChangedEventArgs<RefreshableLayout> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
return;
refreshControl = new UIRefreshControl();
refreshControl.ValueChanged += OnRefresh;
try
{
TryInsertRefresh(this);
}
catch (Exception ex)
{
Debug.WriteLine("View is not supported in PullToRefreshLayout: " + ex);
}
UpdateColors();
UpdateIsRefreshing();
UpdateIsSwipeToRefreshEnabled();
}
bool set;
nfloat origininalY;
bool TryOffsetRefresh(UIView view, bool refreshing, int index = 0)
{
if (view is UITableView)
{
var uiTableView = view as UITableView;
if (!set)
{
origininalY = uiTableView.ContentOffset.Y;
set = true;
}
if (refreshing)
uiTableView.SetContentOffset(new CoreGraphics.CGPoint(0, origininalY - refreshControl.Frame.Size.Height), true);
else
uiTableView.SetContentOffset(new CoreGraphics.CGPoint(0, origininalY), true);
return true;
}
if (view is UICollectionView)
{
var uiCollectionView = view as UICollectionView;
if (!set)
{
origininalY = uiCollectionView.ContentOffset.Y;
set = true;
}
if (refreshing)
uiCollectionView.SetContentOffset(new CoreGraphics.CGPoint(0, origininalY - refreshControl.Frame.Size.Height), true);
else
uiCollectionView.SetContentOffset(new CoreGraphics.CGPoint(0, origininalY), true);
return true;
}
if (view is UIWebView)
{
//can't do anything
return true;
}
if (view is UIScrollView)
{
var uiScrollView = view as UIScrollView;
if (!set)
{
origininalY = uiScrollView.ContentOffset.Y;
set = true;
}
if (refreshing)
uiScrollView.SetContentOffset(new CoreGraphics.CGPoint(0, origininalY - refreshControl.Frame.Size.Height), true);
else
uiScrollView.SetContentOffset(new CoreGraphics.CGPoint(0, origininalY), true);
return true;
}
if (view.Subviews == null)
return false;
for (int i = 0; i < view.Subviews.Length; i++)
{
var control = view.Subviews[i];
if (TryOffsetRefresh(control, refreshing, i))
return true;
}
return false;
}
bool TryInsertRefresh(UIView view, int index = 0)
{
if (view is UITableView)
{
var uiTableView = view as UITableView;
uiTableView = view as UITableView;
view.InsertSubview(refreshControl, index);
return true;
}
if (view is UICollectionView)
{
var uiCollectionView = view as UICollectionView;
uiCollectionView = view as UICollectionView;
view.InsertSubview(refreshControl, index);
return true;
}
if (view is UIWebView)
{
var uiWebView = view as UIWebView;
uiWebView.ScrollView.InsertSubview(refreshControl, index);
return true;
}
if (view is UIScrollView)
{
var uiScrollView = view as UIScrollView;
view.InsertSubview(refreshControl, index);
uiScrollView.AlwaysBounceVertical = true;
return true;
}
if (view.Subviews == null)
return false;
for (int i = 0; i < view.Subviews.Length; i++)
{
var control = view.Subviews[i];
if (TryInsertRefresh(control, i))
return true;
}
return false;
}
BindableProperty rendererProperty;
BindableProperty RendererProperty
{
get
{
if (rendererProperty != null)
return rendererProperty;
var type = Type.GetType("Xamarin.Forms.Platform.iOS.Platform, Xamarin.Forms.Platform.iOS");
var prop = type.GetField("RendererProperty");
var val = prop.GetValue(null);
rendererProperty = val as BindableProperty;
return rendererProperty;
}
}
void UpdateColors()
{
if (RefreshView == null)
return;
if (RefreshView.RefreshColor != Color.Default)
refreshControl.TintColor = RefreshView.RefreshColor.ToUIColor();
if (RefreshView.RefreshBackgroundColor != Color.Default)
refreshControl.BackgroundColor = RefreshView.RefreshBackgroundColor.ToUIColor();
}
void UpdateIsRefreshing()
{
IsRefreshing = RefreshView.IsRefreshing;
}
void UpdateIsSwipeToRefreshEnabled()
{
refreshControl.Enabled = RefreshView.IsPullToRefreshEnabled;
}
public RefreshableLayout RefreshView
{
get { return Element; }
}
bool isRefreshing;
public bool IsRefreshing
{
get { return isRefreshing; }
set
{
bool changed = IsRefreshing != value;
isRefreshing = value;
if (isRefreshing)
refreshControl.BeginRefreshing();
else
refreshControl.EndRefreshing();
if (changed)
TryOffsetRefresh(this, IsRefreshing);
}
}
void OnRefresh(object sender, EventArgs e)
{
if (RefreshView?.RefreshCommand?.CanExecute(RefreshView?.RefreshCommandParameter) ?? false)
{
RefreshView.RefreshCommand.Execute(RefreshView?.RefreshCommandParameter);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == RefreshableLayout.IsPullToRefreshEnabledProperty.PropertyName)
UpdateIsSwipeToRefreshEnabled();
else if (e.PropertyName == RefreshableLayout.IsRefreshingProperty.PropertyName)
UpdateIsRefreshing();
else if (e.PropertyName == RefreshableLayout.RefreshColorProperty.PropertyName)
UpdateColors();
else if (e.PropertyName == RefreshableLayout.RefreshBackgroundColorProperty.PropertyName)
UpdateColors();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (refreshControl != null)
{
refreshControl.ValueChanged -= OnRefresh;
}
}
}
}
I got the code this tutorial and this GitHub
Edit:
XAML
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SocialNetwork.TestScrollPage" xmlns:local="clr-namespace:SocialNetwork.Renderers">
<ContentPage.Content>
<StackLayout>
<local:RefreshableLayout x:Name="RefreshableLayout" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout>
</StackLayout>
</local:RefreshableLayout>
</StackLayout>
</ContentPage.Content>
CS:
public partial class TestScrollPage : ContentPage
{
public TestScrollPage ()
{
InitializeComponent ();
RefreshableLayout.RefreshCommand = new Command(() => RefreshPage());
}
public void RefreshPage()
{
RefreshableLayout.IsRefreshing = false;
DisplayAlert("ok", "ok", "ok");
}
}
And I navigate to the page using Detail = new TestScrollPage();
Edit 2:
public partial class RefreshableLayout : ContentView
{
public static readonly BindableProperty IsRefreshingProperty =
BindableProperty.Create(nameof(IsRefreshing), typeof(bool), typeof(RefreshableLayout), false);
/// <summary>
/// Gets or sets a value indicating whether this instance is refreshing.
/// </summary>
/// <value><c>true</c> if this instance is refreshing; otherwise, <c>false</c>.</value>
public bool IsRefreshing
{
get { return (bool)GetValue(IsRefreshingProperty); }
set
{
if ((bool)GetValue(IsRefreshingProperty) == value)
OnPropertyChanged(nameof(IsRefreshing));
SetValue(IsRefreshingProperty, value);
}
}
/// <summary>
/// The is pull to refresh enabled property.
/// </summary>
public static readonly BindableProperty IsPullToRefreshEnabledProperty =
BindableProperty.Create(nameof(IsPullToRefreshEnabled), typeof(bool), typeof(RefreshableLayout), true);
/// <summary>
/// Gets or sets a value indicating whether this instance is pull to refresh enabled.
/// </summary>
/// <value><c>true</c> if this instance is pull to refresh enabled; otherwise, <c>false</c>.</value>
public bool IsPullToRefreshEnabled
{
get { return (bool)GetValue(IsPullToRefreshEnabledProperty); }
set { SetValue(IsPullToRefreshEnabledProperty, value); }
}
/// <summary>
/// The refresh command property.
/// </summary>
public static readonly BindableProperty RefreshCommandProperty =
BindableProperty.Create(nameof(RefreshCommand), typeof(ICommand), typeof(RefreshableLayout));
/// <summary>
/// Gets or sets the refresh command.
/// </summary>
/// <value>The refresh command.</value>
public ICommand RefreshCommand
{
get { return (ICommand)GetValue(RefreshCommandProperty); }
set { SetValue(RefreshCommandProperty, value); }
}
/// <summary>
/// Gets the Refresh command
/// </summary>
public static readonly BindableProperty RefreshCommandParameterProperty =
BindableProperty.Create(nameof(RefreshCommandParameter),
typeof(object),
typeof(RefreshableLayout),
null,
propertyChanged: (bindable, oldvalue, newvalue) => ((RefreshableLayout)bindable).RefreshCommandCanExecuteChanged(bindable, EventArgs.Empty));
/// <summary>
/// Gets or sets the Refresh command parameter
/// </summary>
public object RefreshCommandParameter
{
get { return GetValue(RefreshCommandParameterProperty); }
set { SetValue(RefreshCommandParameterProperty, value); }
}
/// <summary>
/// Executes if enabled or not based on can execute changed
/// </summary>
/// <param name="sender"></param>
/// <param name="eventArgs"></param>
void RefreshCommandCanExecuteChanged(object sender, EventArgs eventArgs)
{
ICommand cmd = RefreshCommand;
if (cmd != null)
IsEnabled = cmd.CanExecute(RefreshCommandParameter);
}
/// <summary>
/// Color property of refresh spinner color
/// </summary>
public static readonly BindableProperty RefreshColorProperty =
BindableProperty.Create(nameof(RefreshColor), typeof(Color), typeof(RefreshableLayout), Color.Default);
/// <summary>
/// Refresh color
/// </summary>
public Color RefreshColor
{
get { return (Color)GetValue(RefreshColorProperty); }
set { SetValue(RefreshColorProperty, value); }
}
/// <summary>
/// Color property of refresh background color
/// </summary>
public static readonly BindableProperty RefreshBackgroundColorProperty =
BindableProperty.Create(nameof(RefreshBackgroundColor), typeof(Color), typeof(RefreshableLayout), Color.Default);
/// <summary>
/// Refresh background color
/// </summary>
public Color RefreshBackgroundColor
{
get { return (Color)GetValue(RefreshBackgroundColorProperty); }
set { SetValue(RefreshBackgroundColorProperty, value); }
}
/// <param name="widthConstraint">The available width for the element to use.</param>
/// <param name="heightConstraint">The available height for the element to use.</param>
/// <summary>
/// Optimization as we can get the size here of our content all in DIP
/// </summary>
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
if (Content == null)
return new SizeRequest(new Size(100, 100));
return base.OnMeasure(widthConstraint, heightConstraint);
}
}
Please read this documentation about Xamarin Liver Player. It declares the limitations:
Custom Renderers are not supported for Xamarin Forms.
Also there are some other limitions or issues when you use Xamarin Liver Player. So I recommend you to use simulators or a real physical device to test your project.
If you don't have a Mac. You can also try to download an Enterprise Visual Studio to let the simulators mapping to Windows.
I've been trying to make binding work for two labels in a WinForm, but I can't seem to figure out what I'm doing wrong. Currently, I'm implementing the INotifyPropertyChanged interface, and rigged it to a couple of properties within a Form. The current classes this affects are SessionForm.cs, the actual form, and Session.cs, the place where I keep all the information of the program. The labels in question, which are not mentioned in either class, are L_No, which holds the numerical reference of the Note in the musical Scale, and L_Note, which holds the visceral Note value (e.g. C, C#, etc.).
Allow me to explain what everything does within the classes. The program is designed to test your scale knowledge by asking you, based on the your chosen scale, what nth note of the scale is. You use the buttons on the form to make your choice.
These choices are recorded within the Session class, which has been edited to make this more succinct. The array of integers holds the indices of the notes in relation to the scale array, which is in the Scale object. For example, a typical Note array may hold these values: {1,3,0,2,6,1,3,...}. By using the array in the Scale object as a reference, these would translate into musical notes (e.g. D, F, C, E, B, D, F,...). The player's choices are stored within an array of NoteData objects.
In SessionForm.cs I'm manipulating that information over time. Each time a choice is or isn't made (depending on whether or not they attempted to guess in time), the value of the two Labels are changed: L_No, and L_Note. These two Labels are manipulated by the variables NoteIndex and LastNote, respectively. When these change in value, NotifyPropertyChanged occurs, and then the Labels should be updated...but they're not doing so.
Now, in the design section of the form, in the Properties window, I set up the Text property of each Label to be bound to their respective variables within the form, and set to update upon Property Change, but nothing seems to be working.
So what am I doing wrong?
Session.cs:
public class Session
{
public struct NoteData
{
public int Note;
public bool Correct;
public int GuessTime;
}
public Scale Scale;
/// <summary>
/// Holds the notes for one game
/// </summary>
public int[] Notes { get; private set; }
public NoteData[] Data { get; private set; }
/// <summary>
/// Creates a Session
/// </summary>
/// <param name="difficulty">The difficult of the session, refer to the Resources Class for determination.</param>
/// <param name="scale_used">The scale to be used. Refer to the Resources Class for determination.</param>
/// <param name="notes">The notes being used within this Session</param>
public Session(Resources.Difficulties difficulty, Scale scale_used, int[] notes)
{
ID = DateTime.Now;
Diff = difficulty;
Scale = scale_used;
Notes = notes;
Data = new NoteData[notes.Length];
internalIndex = 0;
}
/// <summary>
/// Stores Note input for each guessed
/// </summary>
/// <param name="index">The index of the note the player is currently on</param>
/// <param name="correct">Was the guess correct?</param>
/// <param name="remaining_time">How long did it take for them to guess?</param>
public void StoreNoteInput(int index, bool correct, int remaining_time)
{
if (internalIndex < Data.Length)
Data[internalIndex++] = new NoteData(index, remaining_time, correct);
}
}
SessionForm.cs:
public partial class SessionForm : Form, INotifyPropertyChanged
{
public Session curSession { get; private set; }
Resources.Notes last_note;
/// <summary>
/// The note index number in relation to the scale
/// </summary>
public int NoteIndex
{
get
{ return note_index; }
private set
{
if (note_index != value)
{
note_index = value;
NotifyPropertyChanged("NoteIndex");
}
}
}
/// <summary>
/// Represents the previous note being tested
/// </summary>
public Resources.Notes LastNote
{
get
{
return last_note;
}
private set
{
if (last_note != value)
{
last_note = value;
NotifyPropertyChanged("LastNote");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void TickDownTimer_Tick(object sender, EventArgs e)
{
remainingTime -= countingDown ? 1000 : 100;
if (remainingTime == 0)
{
if (countingDown)
{
countingDown = false;
TickDownTimer.Interval = 100;
}
if (curIndex > 0)
{
//you ran out of time on the last note
RecordNoteInput(curIndex - 1, false);
}
NextNote();
}
SetTimerText();
}
private void RecordNoteInput(int index, bool correct)
{
curSession.StoreNoteInput(index, correct, remainingTime);
NoteIndex = curSession.Notes[curIndex - 1];
LastNote = curSession.Scale.Notes[NoteIndex];
L_Note.ForeColor = correct ? Color.Green : Color.Red;
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
UPDATE: Here's the binding code that comes from SessionForm.Designer.cs:
this.sessionFormBindingSource1 = new System.Windows.Forms.BindingSource(this.components);
this.sessionFormBindingSource2 = new System.Windows.Forms.BindingSource(this.components);
this.sessionFormBindingSource = new System.Windows.Forms.BindingSource(this.components);
//
// L_Note
//
this.L_Note.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.sessionFormBindingSource1, "LastNote", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged, "C"));
this.L_Note.Text = " ";
//
// L_No
//
this.L_No.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.sessionFormBindingSource2, "NoteIndex", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged, "1", "N0"));
this.L_No.Text = " ";
The problem is the way you call NotifyPropertyChanged:
NotifyPropertyChanged("note_index");
and
NotifyPropertyChanged("last_note");
Just remove the strings from the calls like this
NotifyPropertyChanged();
and everything should be fine.
Edit: If it's not, then your bindings are not initialized correctly. Prove:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
namespace Tests
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
}
class TestForm : Form, INotifyPropertyChanged
{
public TestForm()
{
var label = new Label { Parent = this, Left = 16, Top = 16, AutoSize = false, BorderStyle = BorderStyle.FixedSingle };
label.DataBindings.Add("Text", this, "NoteIndex");
var timer = new Timer { Interval = 200, Enabled = true };
timer.Tick += (sender, e) => NoteIndex = (NoteIndex + 1) % 10;
}
int note_index;
public int NoteIndex
{
get { return note_index; }
private set
{
if (note_index != value)
{
note_index = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
i'm getting an error with this code new RoutedEventHandler(Notifications.showNotifications(window)); saying:
An object reference is required for the non-static field, method, or
property 'Notifications.showNotifications(Window)'
Also, can I get an example of how I could dump out each Dictionary object from within my _notifications object in the runtimeObject class? I need to do this when showNotifications is called!
When I say dump out, based on the test notifications which I try to add in the code, I just want to display a MessageBox to show that they are being added, so using the code above the MessageBox would show:
MessageBox
Error Code: 1, Text: Error 1
Error Code: 2, Text: Normal Message
Error Code: 3, Text: Tip
App.xaml.cs
namespace Test_Project
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Startup
Window main = new MainWindow();
main.Show();
//Attach Event Handlers to MainWindow
if (!attachEventHandlers(main))
{
MessageBox.Show("Fatal Error: Unable to attach event handlers, contact administrator!",
"Fatal Error!",
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
}
}
public bool attachEventHandlers(Window window)
{
//window.MouseMove += new RoutedEventHandler(Notifications.showNotifications(window));
return true;
}
}
public class Notifications
{
/// <summary>
/// Show the notifications
/// </summary>
/// <param name="window"></param>
public void showNotifications(Window window)
{
// Find the resource, then cast it to a runtimeObject
var runtime = (runtimeObject)Application.Current.TryFindResource("runtimeVariables");
//Create messagebox with all the notifications in to test
}
public bool addNotifications()
{
// Find the resource, then cast it to a runtimeObject
var runtime = (runtimeObject)Application.Current.TryFindResource("runtimeVariables");
//Create Dictionary
Dictionary<int, string> arr = new Dictionary<int, string>();
arr.Add(1, "Error 1");
arr.Add(2, "Normal Message");
arr.Add(3, "Tip");
//Create test notifications
runtime.notifications.Add(arr);
return true;
}
}
/// <summary>
/// Global values for use during application runtime
/// </summary>
public class runtimeObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
//Can the application be closed?
private bool _inProgress = false;
public bool inProgress
{
get { return _inProgress; }
set
{
if (_inProgress != value)
{
_inProgress = value;
OnPropertyChanged("inProgress");
}
}
}
/// <summary>
/// Notifications held
/// Array((int)type,(string)"message")
/// </summary>
private List<Dictionary<int, string>> _notifications;
public List<Dictionary<int, string>> notifications
{
get { return _notifications; }
set
{
if (_notifications != value)
{
_notifications = value;
OnPropertyChanged("notifications");
}
}
}
//Selected folder to search in
private int _uploadProgress = 0;
public int uploadProgress
{
get { return _uploadProgress; }
set
{
if (_uploadProgress != value)
{
//int Angle = (_uploadProgress * 360) / 100;
//Classes.CircularProgress.RenderArc(Angle);
_uploadProgress = value;
OnPropertyChanged("uploadProgress");
}
}
}
}
}
I am trying to have an autocomplete feature for a ToolStripTextBox in a C# winform application
It is what I have tried
toolStripTextBox1.AutoCompleteMode = AutoCompleteMode.Suggest;
toolStripTextBox1.AutoCompleteSource = AutoCompleteSource.AllUrl;
But for it to suggest a URL, I should type the URL from the beginning (e.g. http://en.wikipedia.org/wiki/Machine_learn...)
What I look for is something like Firefox autocomplete feature, as I type a title or part of the URL, it shows me the matching URL. For example after I type Machine_learning in the example above, it should suggests http://en.wikipedia.org/wiki/Machine_learning
Any solution please?
By the way, I found this similar question WinForms | C# | AutoComplete in the Middle of a Textbox?, but it gets a custom source (array of string), however I like to use AutoCompleteSource.AllUrl as autocomplete source. Moreover the mentioned link is about a textbox and I can't use it in a toolbar. what I need is a solution fo toolStripTextBox
This is the code I used.
You only need to set AutoCompleteCustomSource.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
namespace System.Windows.Forms
{
/// <summary>
/// The partial auto complete text box.
/// </summary>
/// <remarks>Set only <seealso href="AutoCompleteCustomSource"/></remarks>
public class PartialAutoCompleteTextBox : TextBox
{
/// <summary>
/// Initializes a new instance of the <see cref="PartialAutoCompleteTextBox"/> class.
/// </summary>
public PartialAutoCompleteTextBox()
{
AutoItemWidth = true;
}
/// <summary>
/// Gets or sets a value indicating whether auto item width.
/// </summary>
[DefaultValue(true)]
public bool AutoItemWidth { get; set; }
/// <summary>
/// Gets or sets the drop down list.
/// </summary>
protected ListBox DropDownList { get; set; }
/// <summary>
/// Fire create control.
/// </summary>
protected override void OnCreateControl()
{
base.OnCreateControl();
DropDownList = new ListBox
{
Left = Left,
Top = Top + Height,
Width = Width,
Visible = false,
};
Parent.Controls.Add(DropDownList);
}
/// <summary>
/// Raise an <see cref="System.Windows.Forms.Control.KeyUp" /> event.</summary>
/// <param name="e"><see cref="System.Windows.Forms.KeyEventArgs" />.</param>
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
UpdateDropDown();
}
/// <summary>
/// Raise an <see cref="System.Windows.Forms.Control.KeyDown" /> event.</summary>
/// <param name="e"><see cref="System.Windows.Forms.KeyEventArgs" />.</param>
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
switch (e.KeyCode)
{
case Keys.Tab:
case Keys.Enter:
if (DropDownList.Visible == true)
{
InsertToText(Convert.ToString(DropDownList.SelectedItem));
HideDropDown();
_beforeText = Text;
e.SuppressKeyPress = true;
}
break;
case Keys.Escape:
if (DropDownList.Visible == true)
{
HideDropDown();
}
e.SuppressKeyPress = true;
break;
case Keys.Up:
if (DropDownList.Visible == true)
{
if (DropDownList.SelectedIndex == 0)
{
Focus();
}
else if (DropDownList.SelectedIndex > 0)
{
DropDownList.SelectedIndex--;
}
e.SuppressKeyPress = true;
}
break;
case Keys.Down:
if (DropDownList.Visible == true)
{
if (DropDownList.SelectedIndex < DropDownList.Items.Count - 1)
{
DropDownList.SelectedIndex++;
}
}
else if (e.Modifiers == Keys.Alt)
{
ShowDropDown();
}
break;
}
}
/// <summary>
/// Checks whether the specified key is an input key or a special key that requires preprocessing.
/// </summary>
/// <param name="keyData">The key data.</param>
/// <returns>A bool.</returns>
protected override bool IsInputKey(Keys keyData)
{
switch (keyData)
{
case Keys.Tab:
return DropDownList.Visible = true;
}
return base.IsInputKey(keyData);
}
private void ShowDropDown()
{
DropDownList.Visible = true;
DropDownList.BringToFront();
}
private void HideDropDown()
{
DropDownList.Visible = false;
}
private string _beforeText;
private void UpdateDropDown()
{
if (Text == _beforeText || AutoCompleteCustomSource.Count == 0)
{
return;
}
_beforeText = Text;
var matches = AutoCompleteCustomSource.Cast<string>().Where(x => x.IndexOf(Text, StringComparison.OrdinalIgnoreCase) >= 0).ToArray();
if (matches.Length > 0)
{
ShowDropDown();
DropDownList.SuspendLayout();
DropDownList.Items.Clear();
DropDownList.Items.AddRange(matches);
if (AutoItemWidth == true)
{
SetAutoItemWidth();
}
DropDownList.SelectedIndex = 0;
DropDownList.Height = DropDownList.GetItemHeight(0) * Math.Min(30, matches.Length);
DropDownList.ResumeLayout();
Focus();
}
else
{
HideDropDown();
}
}
private void InsertToText(string selectedItem)
{
Text = selectedItem;
SelectionStart = Text.Length;
}
private void SetAutoItemWidth()
{
using (var graphics = DropDownList.CreateGraphics())
{
var itemWidth = DropDownList.Items.Cast<string>().Min(x => (int)graphics.MeasureString((x) + "_", DropDownList.Font).Width);
DropDownList.Width = Math.Max(DropDownList.Width, itemWidth + 20); // 20 is scrol bar width
}
}
}
}
alt text http://[url=http://www.freeimagehosting.net/][img]http://www.freeimagehosting.net/uploads/06e679a07d.jpg[/img][/url]
How to change the button into image button... the button in the beginning has "Pick a date" when clicked a calender pops out and the when a date is selected a label at the bottom reading the date comes in and the text on the button changes to disabled... i want to palce a imagebutton having a image icon of the calender and rest of the function will be the same....
the code as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
[assembly: TagPrefix("DatePicker", "EWS")]
namespace EclipseWebSolutions.DatePicker
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:DatePicker runat=server>")]
[DefaultEvent("SelectionChanged")]
[ValidationProperty("TextValue")]
public class DatePicker : WebControl, INamingContainer
{
#region Properties
public TextBox txtDate = new TextBox();
public Calendar calDate = new Calendar();
public Button btnDate = new Button();
public Panel pnlCalendar = new Panel();
private enum ViewStateConstants
{
ValidationGroup,
RegularExpression,
ErrorMessage,
RegExText,
CalendarPosition,
FormatString,
ExpandLabel,
CollapseLabel,
ApplyDefaultStyle,
CausesValidation,
}
/// <summary>
/// Defines the available display modes of this calendar.
/// </summary>
public enum CalendarDisplay
{
DisplayRight,
DisplayBelow
}
/// <summary>
/// Where to display the popup calendar.
/// </summary>
[Category("Behaviour")]
[Localizable(true)]
public CalendarDisplay CalendarPosition
{
get
{
if (ViewState[ViewStateConstants.CalendarPosition.ToString()] == null)
{
ViewState[ViewStateConstants.CalendarPosition.ToString()] = CalendarDisplay.DisplayRight;
}
return (CalendarDisplay)ViewState[ViewStateConstants.CalendarPosition.ToString()];
}
set
{
ViewState[ViewStateConstants.CalendarPosition.ToString()] = value;
}
}
/// <summary>
/// Text version of the control's value, for use by ASP.NET validators.
/// </summary>
public string TextValue
{
get { return txtDate.Text; }
}
/// <summary>
/// Holds the current date value of this control.
/// </summary>
[Category("Behaviour")]
[Localizable(true)]
[Bindable(true, BindingDirection.TwoWay)]
public DateTime DateValue
{
get
{
try
{
if (txtDate.Text == "") return DateTime.MinValue;
DateTime val = DateTime.Parse(txtDate.Text);
return val;
}
catch (ArgumentNullException)
{
return DateTime.MinValue;
}
catch (FormatException)
{
return DateTime.MinValue;
}
}
set
{
if (value == DateTime.MinValue)
{
txtDate.Text = "";
}
else
{
txtDate.Text = value.ToShortDateString();
}
}
}
[Category("Behavior"), Themeable(false), DefaultValue("")]
public virtual string ValidationGroup
{
get
{
if (ViewState[ViewStateConstants.ValidationGroup.ToString()] == null)
{
return string.Empty;
}
else
{
return (string)ViewState[ViewStateConstants.ValidationGroup.ToString()];
}
}
set
{
ViewState[ViewStateConstants.ValidationGroup.ToString()] = value;
}
}
/// <summary>
/// The label of the exand button. Shown when the calendar is hidden.
/// </summary>
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("PickDate")]
[Localizable(true)]
public string ExpandButtonLabel
{
get
{
String s = (String)ViewState[ViewStateConstants.ExpandLabel.ToString()];
return ((s == null) ? "PickDate" : s);
}
set
{
ViewState[ViewStateConstants.ExpandLabel.ToString()] = value;
}
}
/// <summary>
/// The label of the collapse button. Shown when the calendar is visible.
/// </summary>
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("Disabled")]
[Localizable(true)]
public string CollapseButtonLabel
{
get
{
String s = (String)ViewState[ViewStateConstants.CollapseLabel.ToString()];
return ((s == null) ? "Disabled" : s);
}
set
{
ViewState[ViewStateConstants.CollapseLabel.ToString()] = value;
}
}
/// <summary>
/// Whether to apply the default style. Disable this if you want to apply a custom style, or to use themes and skins
/// to style the control.
/// </summary>
[Category("Appearance")]
[DefaultValue(true)]
[Localizable(true)]
public bool ApplyDefaultStyle
{
get
{
if (ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()] == null)
{
ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()] = true;
}
return (bool)ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()];
}
set
{
ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()] = value;
}
}
/// <summary>
/// Causes Validation
/// </summary>
[Category("Appearance")]
[DefaultValue(false)]
[Localizable(false)]
public bool CausesValidation
{
get
{
if (ViewState[ViewStateConstants.CausesValidation.ToString()] == null)
{
ViewState[ViewStateConstants.CausesValidation.ToString()] = false;
}
return (bool)ViewState[ViewStateConstants.CausesValidation.ToString()];
}
set
{
ViewState[ViewStateConstants.CausesValidation.ToString()] = value;
btnDate.CausesValidation = value;
}
}
#endregion
#region Events
/// <summary>
/// A day was selected from the calendar control.
/// </summary>
public event EventHandler SelectionChanged;
protected virtual void OnSelectionChanged()
{
if (SelectionChanged != null) // only raise the event if someone is listening.
{
SelectionChanged(this, EventArgs.Empty);
}
}
#endregion
#region Event Handlers
/// <summary>
/// The +/- button was clicked.
/// </summary>
protected void btnDate_Click(object sender, System.EventArgs e)
{
if (!calDate.Visible)
{
// expand the calendar
calDate.Visible = true;
txtDate.Enabled = false;
btnDate.Text = CollapseButtonLabel;
if (DateValue != DateTime.MinValue)
{
calDate.SelectedDate = DateValue;
calDate.VisibleDate = DateValue;
}
}
else
{
// collapse the calendar
calDate.Visible = false;
txtDate.Enabled = true;
btnDate.Text = ExpandButtonLabel;
}
}
/// <summary>
/// A date was selected from the calendar.
/// </summary>
protected void calDate_SelectionChanged(object sender, System.EventArgs e)
{
calDate.Visible = false;
txtDate.Visible = true;
btnDate.Text = ExpandButtonLabel;
txtDate.Enabled = true;
txtDate.Text = calDate.SelectedDate.ToShortDateString();
OnSelectionChanged();
}
#endregion
/// <summary>
/// Builds the contents of this control.
/// </summary>
protected override void CreateChildControls()
{
btnDate.Text = ExpandButtonLabel;
btnDate.CausesValidation = CausesValidation;
txtDate.ID = "txtDate";
calDate.Visible = false;
if (ApplyDefaultStyle)
{
calDate.BackColor = System.Drawing.Color.White;
calDate.BorderColor = System.Drawing.Color.FromArgb(10066329);
calDate.CellPadding = 2;
calDate.DayNameFormat = DayNameFormat.Shortest;
calDate.Font.Name = "Verdana";
calDate.Font.Size = FontUnit.Parse("8pt");
calDate.ForeColor = System.Drawing.Color.Black;
calDate.Height = new Unit(150, UnitType.Pixel);
calDate.Width = new Unit(180, UnitType.Pixel);
calDate.DayHeaderStyle.BackColor = System.Drawing.Color.FromArgb(228, 228, 228);
calDate.DayHeaderStyle.Font.Size = FontUnit.Parse("7pt");
calDate.TitleStyle.Font.Bold = true;
calDate.WeekendDayStyle.BackColor = System.Drawing.Color.FromArgb(255, 255, 204);
}
ConnectEventHandlers();
pnlCalendar.Controls.Add(calDate);
pnlCalendar.Style["position"] = "absolute";
pnlCalendar.Style["filter"] = "alpha(opacity=95)";
pnlCalendar.Style["-moz-opacity"] = ".95";
pnlCalendar.Style["opacity"] = ".95";
pnlCalendar.Style["z-index"] = "2";
pnlCalendar.Style["background-color"] = "White";
if (CalendarPosition == CalendarDisplay.DisplayBelow)
{
pnlCalendar.Style["margin-top"] = "27px";
}
else
{
pnlCalendar.Style["display"] = "inline";
}
Controls.Add(txtDate);
Controls.Add(pnlCalendar);
Controls.Add(btnDate);
base.CreateChildControls();
}
/// <summary>
/// Render the contents of this control.
/// </summary>
/// <param name="output">The HtmlTextWriter to use.</param>
protected override void RenderContents(HtmlTextWriter output)
{
switch (CalendarPosition)
{
case CalendarDisplay.DisplayRight:
{
txtDate.RenderControl(output);
btnDate.RenderControl(output);
pnlCalendar.RenderControl(output);
break;
}
case CalendarDisplay.DisplayBelow:
{
pnlCalendar.RenderControl(output);
txtDate.RenderControl(output);
btnDate.RenderControl(output);
break;
}
}
}
/// <summary>
/// Connect event handlers to events.
/// </summary>
private void ConnectEventHandlers()
{
btnDate.Click += new System.EventHandler(btnDate_Click);
calDate.SelectionChanged += new System.EventHandler(calDate_SelectionChanged);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
[assembly: TagPrefix("DatePicker", "EWS")]
namespace EclipseWebSolutions.DatePicker
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:DatePicker runat=server>")]
[DefaultEvent("SelectionChanged")]
[ValidationProperty("TextValue")]
public class DatePicker : WebControl, INamingContainer
{
#region Properties
public TextBox txtDate = new TextBox();
public Calendar calDate = new Calendar();
public Button btnDate = new Button();
public Panel pnlCalendar = new Panel();
private enum ViewStateConstants
{
ValidationGroup,
RegularExpression,
ErrorMessage,
RegExText,
CalendarPosition,
FormatString,
ExpandLabel,
CollapseLabel,
ApplyDefaultStyle,
CausesValidation,
}
/// <summary>
/// Defines the available display modes of this calendar.
/// </summary>
public enum CalendarDisplay
{
DisplayRight,
DisplayBelow
}
/// <summary>
/// Where to display the popup calendar.
/// </summary>
[Category("Behaviour")]
[Localizable(true)]
public CalendarDisplay CalendarPosition
{
get
{
if (ViewState[ViewStateConstants.CalendarPosition.ToString()] == null)
{
ViewState[ViewStateConstants.CalendarPosition.ToString()] = CalendarDisplay.DisplayRight;
}
return (CalendarDisplay)ViewState[ViewStateConstants.CalendarPosition.ToString()];
}
set
{
ViewState[ViewStateConstants.CalendarPosition.ToString()] = value;
}
}
/// <summary>
/// Text version of the control's value, for use by ASP.NET validators.
/// </summary>
public string TextValue
{
get { return txtDate.Text; }
}
/// <summary>
/// Holds the current date value of this control.
/// </summary>
[Category("Behaviour")]
[Localizable(true)]
[Bindable(true, BindingDirection.TwoWay)]
public DateTime DateValue
{
get
{
try
{
if (txtDate.Text == "") return DateTime.MinValue;
DateTime val = DateTime.Parse(txtDate.Text);
return val;
}
catch (ArgumentNullException)
{
return DateTime.MinValue;
}
catch (FormatException)
{
return DateTime.MinValue;
}
}
set
{
if (value == DateTime.MinValue)
{
txtDate.Text = "";
}
else
{
txtDate.Text = value.ToShortDateString();
}
}
}
[Category("Behavior"), Themeable(false), DefaultValue("")]
public virtual string ValidationGroup
{
get
{
if (ViewState[ViewStateConstants.ValidationGroup.ToString()] == null)
{
return string.Empty;
}
else
{
return (string)ViewState[ViewStateConstants.ValidationGroup.ToString()];
}
}
set
{
ViewState[ViewStateConstants.ValidationGroup.ToString()] = value;
}
}
/// <summary>
/// The label of the exand button. Shown when the calendar is hidden.
/// </summary>
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("PickDate")]
[Localizable(true)]
public string ExpandButtonLabel
{
get
{
String s = (String)ViewState[ViewStateConstants.ExpandLabel.ToString()];
return ((s == null) ? "PickDate" : s);
}
set
{
ViewState[ViewStateConstants.ExpandLabel.ToString()] = value;
}
}
/// <summary>
/// The label of the collapse button. Shown when the calendar is visible.
/// </summary>
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("Disabled")]
[Localizable(true)]
public string CollapseButtonLabel
{
get
{
String s = (String)ViewState[ViewStateConstants.CollapseLabel.ToString()];
return ((s == null) ? "Disabled" : s);
}
set
{
ViewState[ViewStateConstants.CollapseLabel.ToString()] = value;
}
}
/// <summary>
/// Whether to apply the default style. Disable this if you want to apply a custom style, or to use themes and skins
/// to style the control.
/// </summary>
[Category("Appearance")]
[DefaultValue(true)]
[Localizable(true)]
public bool ApplyDefaultStyle
{
get
{
if (ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()] == null)
{
ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()] = true;
}
return (bool)ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()];
}
set
{
ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()] = value;
}
}
/// <summary>
/// Causes Validation
/// </summary>
[Category("Appearance")]
[DefaultValue(false)]
[Localizable(false)]
public bool CausesValidation
{
get
{
if (ViewState[ViewStateConstants.CausesValidation.ToString()] == null)
{
ViewState[ViewStateConstants.CausesValidation.ToString()] = false;
}
return (bool)ViewState[ViewStateConstants.CausesValidation.ToString()];
}
set
{
ViewState[ViewStateConstants.CausesValidation.ToString()] = value;
btnDate.CausesValidation = value;
}
}
#endregion
#region Events
/// <summary>
/// A day was selected from the calendar control.
/// </summary>
public event EventHandler SelectionChanged;
protected virtual void OnSelectionChanged()
{
if (SelectionChanged != null) // only raise the event if someone is listening.
{
SelectionChanged(this, EventArgs.Empty);
}
}
#endregion
#region Event Handlers
/// <summary>
/// The +/- button was clicked.
/// </summary>
protected void btnDate_Click(object sender, System.EventArgs e)
{
if (!calDate.Visible)
{
// expand the calendar
calDate.Visible = true;
txtDate.Enabled = false;
btnDate.Text = CollapseButtonLabel;
if (DateValue != DateTime.MinValue)
{
calDate.SelectedDate = DateValue;
calDate.VisibleDate = DateValue;
}
}
else
{
// collapse the calendar
calDate.Visible = false;
txtDate.Enabled = true;
btnDate.Text = ExpandButtonLabel;
}
}
/// <summary>
/// A date was selected from the calendar.
/// </summary>
protected void calDate_SelectionChanged(object sender, System.EventArgs e)
{
calDate.Visible = false;
txtDate.Visible = true;
btnDate.Text = ExpandButtonLabel;
txtDate.Enabled = true;
txtDate.Text = calDate.SelectedDate.ToShortDateString();
OnSelectionChanged();
}
#endregion
/// <summary>
/// Builds the contents of this control.
/// </summary>
protected override void CreateChildControls()
{
btnDate.Text = ExpandButtonLabel;
btnDate.CausesValidation = CausesValidation;
txtDate.ID = "txtDate";
calDate.Visible = false;
if (ApplyDefaultStyle)
{
calDate.BackColor = System.Drawing.Color.White;
calDate.BorderColor = System.Drawing.Color.FromArgb(10066329);
calDate.CellPadding = 2;
calDate.DayNameFormat = DayNameFormat.Shortest;
calDate.Font.Name = "Verdana";
calDate.Font.Size = FontUnit.Parse("8pt");
calDate.ForeColor = System.Drawing.Color.Black;
calDate.Height = new Unit(150, UnitType.Pixel);
calDate.Width = new Unit(180, UnitType.Pixel);
calDate.DayHeaderStyle.BackColor = System.Drawing.Color.FromArgb(228, 228, 228);
calDate.DayHeaderStyle.Font.Size = FontUnit.Parse("7pt");
calDate.TitleStyle.Font.Bold = true;
calDate.WeekendDayStyle.BackColor = System.Drawing.Color.FromArgb(255, 255, 204);
}
ConnectEventHandlers();
pnlCalendar.Controls.Add(calDate);
pnlCalendar.Style["position"] = "absolute";
pnlCalendar.Style["filter"] = "alpha(opacity=95)";
pnlCalendar.Style["-moz-opacity"] = ".95";
pnlCalendar.Style["opacity"] = ".95";
pnlCalendar.Style["z-index"] = "2";
pnlCalendar.Style["background-color"] = "White";
if (CalendarPosition == CalendarDisplay.DisplayBelow)
{
pnlCalendar.Style["margin-top"] = "27px";
}
else
{
pnlCalendar.Style["display"] = "inline";
}
Controls.Add(txtDate);
Controls.Add(pnlCalendar);
Controls.Add(btnDate);
base.CreateChildControls();
}
/// <summary>
/// Render the contents of this control.
/// </summary>
/// <param name="output">The HtmlTextWriter to use.</param>
protected override void RenderContents(HtmlTextWriter output)
{
switch (CalendarPosition)
{
case CalendarDisplay.DisplayRight:
{
txtDate.RenderControl(output);
btnDate.RenderControl(output);
pnlCalendar.RenderControl(output);
break;
}
case CalendarDisplay.DisplayBelow:
{
pnlCalendar.RenderControl(output);
txtDate.RenderControl(output);
btnDate.RenderControl(output);
break;
}
}
}
/// <summary>
/// Connect event handlers to events.
/// </summary>
private void ConnectEventHandlers()
{
btnDate.Click += new System.EventHandler(btnDate_Click);
calDate.SelectionChanged += new System.EventHandler(calDate_SelectionChanged);
}
}
}
Untitled Page
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void DatePicker1_SelectionChanged(object sender, EventArgs e)
{
Label1.Text = DatePicker1.DateValue.ToShortDateString();
pnlLabel.Update();
}
}
to make the button an image you could just style it to add a background image.
btnDate.style["background-image"] ="url(images/btn.jpg)";
btnDate.text="";
In Html, an image button has a type attribute of 'image' and a src attribute used to determine the image to be displayed. So, to change a standard button to an image button you would:
buttonControl.Attributes["type"] = "image";
buttonControl.Attributes["src"] = "Foo.jpg";
EDIT
If you are trying to change the button type in the click event, then you might be required to do that via javascript client-side. You can do that by registering a start-up script in the Click event like so:
protected void Button_OnClick( object sender, EventArgs e )
{
var button = sender as Button;
if ( button == null )
return;
var jsScript = new StringBuilder();
jsScript.AppendFormat( "<script type=\"text/javascript\">" );
jsScript.AppendFormat( "var button = document.getElementById(\"{0}\"); button.type = \"image\"; button.src=\"Foo.jpg\";"
, button.ClientID);
jsScript.Append( "</script>" );
if ( !Page.ClientScript.IsStartupScriptRegistered( typeof( Page ), "resetImageButton" ) )
Page.ClientScript.RegisterStartupScript( typeof( Page ), "resetImageButton", jsScript.ToString(), false );
}
The catch is that this will only work right after the postback triggered by clicking the button. It will not survive multiple postbacks. For that, you would need to store a flag in a hidden text field or ViewState that indicates which type the button should be and then, based on that, determine whether you need to register this startup script or not.