WP7 silverlight custom control using popup - c#

I'm creating a custom datepicker, I have a textbox, once clicked it opens a calendar within a popup.
What I want to do is change the size of the popup so it shows my whole calendar, but I can't manage to change it..., I've tried using Height, Width, MinHeight, MinWidth... but it doesn't work, the popup keep showing with a fixed size.
The thing is that my popup's parent property isn't evaluated since it has expression issues (according to debugger), so I'm sure my popup's parent isn't the main screen( say layout grid).
How can I for example make my popup open within a specific context ?
This part of my code isn't XAML, it's C# code only and it looks like:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
namespace CalendarBranch.components
{
public class wpDatePicker:TextBox
{
private CalendarPopup calendar;
private Popup popup;
public wpDatePicker()
{
this.calendar = new CalendarPopup();
this.popup = new Popup();
this.popup.Child = this.calendar;
this.popup.Margin = new Thickness(0);
this.MouseLeftButtonUp += new MouseButtonEventHandler(wpDatePicker_MouseLeftButtonUp);
this.calendar.onDateSelect += new EventHandler(onDateSelected);
this.IsReadOnly = true;
}
protected void wpDatePicker_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.popup.Height = this.calendar.Height;
this.popup.Width = this.calendar.Width;
this.popup.HorizontalAlignment = HorizontalAlignment.Center;
this.popup.VerticalAlignment = VerticalAlignment.Center;
this.popup.HorizontalOffset = 0;
this.popup.VerticalOffset = 0;
this.popup.MinHeight = this.calendar.Height;
this.popup.MinWidth = this.calendar.Width;
this.popup.IsOpen = true;
}
private void onDateSelected(Object sender, EventArgs ea) {
this.Text = this.calendar.SelectedValue.ToShortDateString();
this.popup.IsOpen = false;
}
}
}
PS: the class Calendar is simply a UserControl that contains a grid with multiple columns, HyperLinkButtons and TextBlocks, so nothing special.
Thank you in advance guys ;)
Cheers
Miloud B.

Popup control resizes itself to fit the content inside of it. For example, if you set the child of Popup to be StackPanel with width/height set to 100, the popup will be 100x100.
So it's really important to set the sizes not of your popup, but of your inner panel. Try wrapping your content into the stackpanel and assign necessary width/height there.

Related

Xamarin forms - Remove burger menu icon but keep nav bar

I'm wanting to remove the burger menu icon whilst retaining the navigation bar. I want to add content to the NavigationPage.TitleView property and i would like it to take the full width of the page. In the image i've attached, the yellow background colour shows the width that the TitleView is currently occupying.
I know in forms you can control the visibility of the back button, is there a way you can also control the burger menu icon? Based on what i've been reading, this will most likely require a custom renderer, which i've tried with no luck. I need to support iOS & Android.
In the android, you can use following custom renderer code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.Graphics.Drawable;
using Android.Views;
using Android.Widget;
using MesterDetailspage.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android.AppCompat;
[assembly: ExportRenderer(typeof(MasterDetailPage), typeof(MyMasterDetailRenderer))]
namespace MesterDetailspage.Droid
{
public class MyMasterDetailRenderer : MasterDetailPageRenderer
{
public MyMasterDetailRenderer(Context context) : base(context)
{
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
if (toolbar != null)
{
for (var i = 0; i < toolbar.ChildCount; i++)
{
var imageButton = toolbar.GetChildAt(i) as Android.Widget.ImageButton;
var drawerArrow = imageButton?.Drawable as DrawerArrowDrawable;
if (drawerArrow == null)
continue;
bool displayBack = false;
var app = Xamarin.Forms.Application.Current;
var detailPage = (app.MainPage as MasterDetailPage).Detail;
var navPageLevel = detailPage.Navigation.NavigationStack.Count;
if (navPageLevel > 1)
displayBack = true;
if (!displayBack)
ChangeIcon(imageButton, Resource.Drawable.test1);
if (displayBack) ;
//ChangeIcon(imageButton, Resource.Drawable.back1);
}
}
}
private void ChangeIcon(Android.Widget.ImageButton imageButton, int id)
{
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Lollipop)
imageButton.SetImageDrawable(Context.GetDrawable(id));
imageButton.SetImageResource(id);
}
}
}
I set a transparent background image.
Here is running screenshot.
For iOS, just set the IconImageSource="test1.png" in MasterDetailPage tag in xamarin forms xaml.
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
IconImageSource="test1.png"
xmlns:views="clr-namespace:MesterDetailspage.Views"
x:Class="MesterDetailspage.Views.MainPage">
As it turns out, at the moment, this is not possible. You can hide the burger menu but it still takes up space (see Leon Lu's answer).
My solution was to create a custom navigation bar, that way i have full control. If you want to do this first remove the navigation bar:
NavigationPage.SetHasNavigationBar(this, false);
Then add your custom nav using regular xaml code, just like you would with any other component.
One to thing to keep in mind is that in ios your nav can show where the notch is, to fix this you need to use this code:
On<iOS>().SetUseSafeArea(true);

Children don't seem to want to fill the FlowLayout as expected (C#)

I'm new to C# and may be missing something obvious. I've found only one related question here, and it was not exactly a match nor very authoritative.
What I want is to make it so that I can dock a control inside a FlowLayout (set left-to-right) so that it will fill the whole vertical space, and when the user resizes the Form, the controls resize to continue filling the whole vertical space. Can this be done, and if so, how?
What I've found:
I've created a Form. I've coloured it red. I've added a FlowLayout which I've coloured green and set the Dock to fill the Form. This seems to work (the Form is now all green, no red visible).
I then add a couple of controls to the FlowLayout (which is running left-to-right). If I dock them top, it works as expected. If I dock them bottom, it is the same as top; suggesting the vertical space is not really the whole green area. Docking left, right or fill the components won't appear at all unless I give them a minimum size > 0.
I have some code which shows what I mean; I have added some size to one of the controls and it can be seen that this seems to resize to the minimum vertical size allowed. The output screenshot is included.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ViewData
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CustomComponentLayout();
}
private void CustomComponentLayout()
{
FlowLayoutPanel pnlHorFlow;
pnlHorFlow = new FlowLayoutPanel();
this.Controls.Add(pnlHorFlow);
pnlHorFlow.Dock = DockStyle.Fill;
pnlHorFlow.BackColor = Color.Green;
// Add a panel with some size
Panel testPanel = new Panel();
testPanel.Dock = DockStyle.Fill;
testPanel.BackColor = Color.BlanchedAlmond;
// Need these to get anything
testPanel.MinimumSize = new Size(200, 400);
pnlHorFlow.Controls.Add(testPanel);
Button testButton;
testButton = new Button();
testButton.Text = "Test";
testButton.Anchor = AnchorStyles.Top & AnchorStyles.Bottom;
testButton.Dock = DockStyle.Left;
pnlHorFlow.Controls.Add(testButton);
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
EDIT
Ok, so the answer below doesn't answer the question, but I've accepted it because I am now convinced that the answer is that FlowLayoutPanel just can't do this. The answer (at least the edit) is about as close as I'll get. Playing with TableLayoutPanel seems to be the only way to get what I need.
For those in this boat, I also found this helpful.
I've found a lot of people making the same wrong assumptions about FlowLayoutPanel as me. I think in my case it ius because I have a Java background, and FlowLayouts work differently in Java.
Here is an example of using AnchorStyles.Right:
public class FlowForm2 : Form {
public FlowForm2() {
Button btn1 = new Button { Text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", AutoSize = true };
Button btn2 = new Button { Text = "ABCD", AutoSize = true };
btn2.Anchor = AnchorStyles.Right;
FlowLayoutPanel p = new FlowLayoutPanel { Dock = DockStyle.Fill, FlowDirection = FlowDirection.TopDown, WrapContents = false };
p.Controls.Add(btn1); // if btn1 isn't added, then btn2 appears on the LEFT side
p.Controls.Add(btn2); // however, if btn1 is added, then btn2 is right justified with the right edge of btn2
Controls.Add(p);
}
}
EDIT:
The easiest way to create the layout you want is:
public class TLPForm : Form {
TableLayoutPanel p = new TableLayoutPanel { Dock = DockStyle.Fill };
public TLPForm() {
var style = AnchorStyles.Top | AnchorStyles.Bottom;
Button btn1 = new Button { Text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", AutoSize = true, AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink, Anchor = style };
Button btn2 = new Button { Text = "ABCD", AutoSize = true, AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink, Anchor = style };
Button btn3 = new Button { Text = "ABCD", AutoSize = true, AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink, Anchor = style };
p.Controls.Add(btn1, 0, 0);
p.Controls.Add(btn2, 1, 0);
p.Controls.Add(btn3, 2, 0);
p.Controls.Add(new Control(), 3, 0); // <-- takes up the rest of the space
Controls.Add(p);
}
}

Displaying a text box

I've searched the questions for an answer but couldn't quite find a clear cut example. I am trying to display a simple text box in C#. I am working with C#, ArcMap and ArcObjects. I have created a toolbar that has a button in it. Upon clicking the button, I just need a text box to appear on the page. So far, this is what I've got, but nothing is producing when I click my button. Thanks for your help in advance.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
namespace Map
{
public class ArcGISAddin4 : ESRI.ArcGIS.Desktop.AddIns.Button
{
public ArcGISAddin4()
{
}
protected override void OnClick()
{
TextBox dynamicTextBox = new TextBox();
dynamicTextBox.Text = "My First Text Box";
dynamicTextBox.Name = "First Text Box";
dynamicTextBox.Enabled = true;
}
protected override void OnUpdate()
{
}
}
}
You must add the TextBox to the surrounding container (the form for example). Otherwise the program won't know where it's supposed to be displayed.
You should add dynamicTextBox to a specific container such as form.
Such as this:
TextBox dynamicTextBox = new TextBox();
dynamicTextBox.Text = "My First Text Box";
dynamicTextBox.Name = "First Text Box";
dynamicTextBox.Enabled = true;
this.Contols.Add(dynamicTextBox);//this is a pseudo code

change font style in c#

hi there I want to change the font style of a label in an aspx page, through choosing options provided by a dorpdownlist. None of these methods work. I know I might be on the right path, but just can't seem to get it right. Please enlighten me. Thanks
In my code behind:
public void button1_Click(object sender, EventArgs e)
{
var select= drop1.SelectedItem.Value;
if(select == "Times New Roman")
{
// I tried doing all of these:
label1.Font= new Font("Times New Roman", label1.Font.Size);
//or
label1.Font.Name ="Times New Roman";
//or
Label new1 = new Label("Times New Roman");
Label1.Font= new1;
}
}
You're better off using jquery
Bind an event handler to the onchange event on the select dropdown and according to the value then change the css class. This has the benefits of a - not being server side and avoiding a hit on the server b - easier c - cleaner
edit : Something like this could be adapted
jQuery onchange/onfocus select box to display an image?
Do you need to make it this way? It's not a 'nice' solution anyway. It's much better to assign an css class. I haven't seen this way before... but I would say that it's comming from WinForms.
Use CssClass instead:
label1.CssClass = "SomeClass";
And define styling in your stylesheet:
.SomeClass { font-family: "Times New Roman"; font-size: 1.2em; }
here is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication2
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Font.Name = "Verdana";
}
}
}
and it is working, i just need you to make sure that before you run the application you set a fontname to your label because the fontname is empty when you put it in your page,(it doesnt work if you dont set a fontname initially) you need to set it then yuse the code i wrte above.open the properties window click the label and click font then choose a name for font name
On web we do not create new Font this works for desktop programming and the new Font are made on server not on client.
The Label contains the .Font but not to set a new font, but to actually create a new inline style, and the object is the FontInfo (not the Font).
From MSDN FontInfo here is an example:
// Note that myLabel.Font is a FontInfo object.
myLabel.Font.Bold = true;
myLabel.Font.Italic = false;
myLabel.Font.Name = "verdana";
myLabel.Font.Overline = false;
myLabel.Font.Size = 10;
myLabel.Font.Strikeout = false;
myLabel.Font.Underline = true;
// Write information on the FontInfo object to the myLabel label.
myLabel.Text = myLabel.Font.ToString();
The final render of this contains inline style to give this properties to the text that is inside a span or a div. Is better of course to give a global css class, but some times you need to interfere with inline style.

Using WPF on a DLL to create Images Dynamically (instead of GDI+)

I need to generate an image dynamically, and after I read the tutorial here I realize i can use all the controls and layouts from WPF to generate my rendering, and then save it as a JPG.
The idea is to use this instead of GDI+, which is quite primitive.
The question is, how to I create a regular dll file that would generate programatically a WPF canvas so then i can add controls to it and then ouput that to an image file. Keep in mind that it would be consumed by an ASP.NET application.
Any ideas somebody?
That example has a good start but I've found it's got a lot of unneeded junk along with it. The main thing is that you don't need to have a separate WPF project.
Here's what to do:
Reference PresentationCore, PresentationFramework and WindowsBase in your web project.
Create a Canvas and other WPF objects programmatically in an STA thread.
Call a few special methods on them to make sure they update outside of the context of a WPF app.
Render them to an image with RenderTargetBitmap.
Shut down the thread's dispatcher.
Set the mime type and output the image with ASP.NET.
To make this more efficient you could re-use the same thread rather than creating a new one for each image. In that case you would only need to clean up the dispatcher when you shut down the thread.
Here's the full working code I have:
using System;
using System.Web;
using System.Threading;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Controls;
using System.Windows.Documents;
public partial class _Default : System.Web.UI.Page
{
private byte[] imageBuffer;
public void Page_Load(object sender, EventArgs e)
{
this.RenderImage();
Response.Clear();
Response.ContentType = #"image/png";
Response.BufferOutput = true;
Response.BinaryWrite(this.imageBuffer);
Response.Flush();
}
public void RenderImage()
{
Thread worker = new Thread(new ThreadStart(this.RenderImageWorker));
worker.SetApartmentState(ApartmentState.STA);
worker.Name = "RenderImageWorker";
worker.Start();
worker.Join();
}
public void RenderImageWorker()
{
Canvas imageCanvas = new Canvas { Width = 600, Height = 200, Background = Brushes.Azure };
TextBlock tb = new TextBlock();
tb.Width = (double)400;
//tb.Height = (double)200;
tb.TextAlignment = TextAlignment.Center;
tb.Inlines.Add(new Run("This is "));
tb.Inlines.Add(new Bold(new Run("bold")));
tb.Inlines.Add(new Run(" text."));
tb.FontSize = 30;
tb.Foreground = Brushes.Blue;
imageCanvas.Children.Add(tb);
// Update layout
imageCanvas.Measure(new Size(imageCanvas.Width, imageCanvas.Height));
imageCanvas.Arrange(new Rect(new Size(imageCanvas.Width, imageCanvas.Height)));
RenderTargetBitmap bitmapRenderer = new RenderTargetBitmap((int)imageCanvas.ActualWidth, (int)imageCanvas.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bitmapRenderer.Render(imageCanvas);
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(bitmapRenderer));
using (MemoryStream memoryStream = new MemoryStream())
{
png.Save(memoryStream);
this.imageBuffer = memoryStream.ToArray();
}
if (bitmapRenderer.Dispatcher.Thread.IsAlive)
{
bitmapRenderer.Dispatcher.InvokeShutdown();
}
}
}

Categories

Resources