I have a form done in WPF which has a custom control already on it called RateView. This custom control has 4 textboxes (which are all working as they should be). It also contains a button.
I have a second custom control called Extended Margin Info, which also has a XAML Form which will just show output data only.
How can I by clicking the button on the custom control called Rateview bring up the XAML canvas onto my Main window of the extendedmargin info XAML, in the same position everytime? Rateview control exists 5 times on the main window therfore there will be 5 buttons that when clicked, will need to output the popup of ExtendedMargin Info to the main screen in the same position each time with the content of extendedmargin info.
Your button, when clicked, should call a Command which updates a Property of some ViewModel that exposes the ViewModel of the current ExtendedMarginInfo you want to display. Then you can bind this property to the Content Property of a ContentControl in the target view. You can select the View you want the Control to display by using the ContentControl.ContentTemplateSelector property.
I guess you want show one popup and change it's content placing in it different controls.
At 1st create your custom control:
balloon = new LogEntryInfoBalloon();
balloon.SetMainWindow(this);
balloon.DataContext = vm.NotificationViewModel;
Then create Popup control (System.Windows.Controls.Primitives):
localPop = new Popup();
localPop.AllowsTransparency = true;
localPop.Placement = PlacementMode.AbsolutePoint;
localPop.StaysOpen = true;
localPop.PlacementTarget = this;
localPop.Child = balloon;
Placement target points to MainWindow.
Define timer that will close(hide) balloon:
localPopTimer = new Timer(new TimerCallback(CloseLocalPopup));
Close func:
private void CloseLocalPopup(object args)
{
var act = new Action(() =>
{
localPop.IsOpen = false;
});
Dispatcher.BeginInvoke(act, null);
}
Show balloon code looks like this:
private void ShowNotifyBaloon(NotifyBaloonViewModel vm)
{
var act = new Action(() =>
{
localPop.IsOpen = true;
localPopTimer.Change(4000, Timeout.Infinite);
});
Dispatcher.BeginInvoke(act, null);
}
Related
MessageBoxEx
I trying to implement XAML into CS. It succeeded but only 1 thing I can't solve and that is:
Convert this to ContentControl.
object parent = this;
MessageBoxEx.SetParentWindow(this);
The parent windows must be set otherwise I get a null reference.
Can somebody help me out?
Found the solution
public void InitMessageBox()
{
// Create the ElementHost control for hosting the
// WPF UserControl.
ContentControl host = new ContentControl();
host.DataContext = this;
//host.Dock = DockStyle.Fill;
// Create the WPF UserControl.
MessageBoxEx uc =
new MessageBoxEx();
// Assign the WPF UserControl to the ElementHost control's
// Child property.
//host.Parent = this;
//host.Child = uc;
// Add the ElementHost control to the form's
// collection of child controls.
//this.Controls.Add(host);
// p = (ContentControl) this;
MessageBoxEx.SetParentWindow(host);
MessageBoxEx.SetMessageForeground(Colors.White);
MessageBoxEx.SetMessageBackground(Colors.Black);
MessageBoxEx.SetButtonBackground(MessageBoxEx.ColorFromString("#333333"));
MessageBoxEx.SetButtonTemplateName("AefCustomButton");
MessageBoxEx.SetMaxFormWidth(600);
MessageBoxEx.SetErrorDelegate(new ErrorMsgDelegate());
// if you want to make the MessageBoxEx silent when you use icons, uncomment the next line
//MessageBoxEx.SetAsSilent(true);
}
I have not done this but you must follow a special procedure to use a WPF control with Windows Forms. Please see this link: Use WPF controls in Windows Forms apps
I've some code found:
public void InitMessageBox()
{
// Create the ElementHost control for hosting the
// WPF UserControl.
ElementHost host = new ElementHost();
host.Dock = DockStyle.Fill;
// Create the WPF UserControl.
MsgBoxEx.MessageBoxEx uc =
new MsgBoxEx.MessageBoxEx();
// Assign the WPF UserControl to the ElementHost control's
// Child property.
host.Parent = this;
host.Child = uc; // Error
// Add the ElementHost control to the form's
// collection of child controls.
this.Controls.Add(host); // host = error
// p = (ContentControl) this;
MessageBoxEx.SetParentWindow(uc);
MessageBoxEx.SetMessageForeground(Colors.White);
MessageBoxEx.SetMessageBackground(Colors.Black);
MessageBoxEx.SetButtonBackground(MessageBoxEx.ColorFromString("#333333"));
MessageBoxEx.SetButtonTemplateName("AefCustomButton");
MessageBoxEx.SetMaxFormWidth(600);
MessageBoxEx.SetErrorDelegate(new ErrorMsgDelegate());
// if you want to make the MessageBoxEx silent when you use icons, uncomment the next line
//MessageBoxEx.SetAsSilent(true);
}
This code I have from internet but does not work
I have created ribbon form (XtraMain)and I set IsMdiContainer Property to true,i also add documentManager controle i set MdiParent to XtraMain I have add this code to open child forms
public void ViewChildForm(XtraForm _form)
{
if (!IsFormActived(_form))
{
_form.MdiParent = this;
_form.Show();
}
}
private bool IsFormActived(XtraForm form)
{
bool IsOpenend = false;
if (MdiChildren.Count() > 0)
{
foreach (var item in MdiChildren)
{
if (form.Name == item.Name)
{
tabbedView1.ActivateDocument(item);
IsOpenend = true;
}
}
}
return IsOpenend;
}
and i use this code in click of button to open the child form
private void bbtnEmployee_ItemClick(object sender, ItemClickEventArgs e)
{
FrmEmployee frme = new FrmEmployee();
frme.Name = "FrmEmployee";
ViewChildForm(frme);
}
my problem start when the form contain a LayoutControl for example i have this code that open on click of button
private void btnBonLivraison_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
LayoutControl lc = new LayoutControl();
lc.Dock = DockStyle.Top;
LookUpEdit OrderNumber = new LookUpEdit();
OrderNumber.Properties.TextEditStyle = TextEditStyles.DisableTextEditor;
OrderNumber.Properties.DataSource = shippProdu.GetOrderNumber();
OrderNumber.Properties.DisplayMember = "N° Bon de livraison";
OrderNumber.Properties.ValueMember = "N° Bon de livraison";
lc.AddItem(Resources.selectOrderNumber, OrderNumber).TextVisible = true;
lc.Height = 70;
this.Controls.Add(lc);
this.Dock = DockStyle.Top;
lc.BestFit();
the second I click on a button the tabHeader disappears,what cause this problem?and how can I solve it.before I use documentManager I used XtraTabControl and if i click a button to open LayoutControl and after that try to open another form the focus remaining in the first form even when the form two is already opened and if I want to go to form two I must first click on a tab of the first form and then click on tab of the second form , thanks in advance .
this is my main form
and this is when the eader disappears
If DocumentManager resides within the same form to which you add LayoutControl, it is the expected behavior. DocumentManager places a special documents' host onto the main form and set its Dock property to Fill. That is why it is incorrect to place LayoutControl onto the same form and dock it to form edges.
If you need to show tabbed documents and LayoutControl on the same form simultaneously, do not use the MDI mode. Consider the use of a separate UserControl. Place your DocumentManager there. Then, put this UserControl onto your form. Note that in this case UserControl's Dock property should be set to Top or Bottom since LayoutControl should fill all available area or vice versa.
I'm trying to create a custom container as UserControl.
My Goal: I want to be able to drag controls inside the designer and handle incoming controls inside the code of my usercontrol.
Example: I place my container somewhere and then add a button. In this momemt I want my usercontrol to automatically adjust the width and position of this button. Thats the point where Im stuck.
My code:
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class ContactList : UserControl
{
public ContactList()
{
InitializeComponent();
}
private void ContactList_ControlAdded(object sender, ControlEventArgs e)
{
e.Control.Width = 200; // Nothing happens
e.Control.Height = 100; // Nothing happens
MessageBox.Show("Test"); // Firing when adding a control
}
}
The MessageBox is working well. The set width and height is ignored.
The question is just "why?".
EDIT
I've just noticed, when placing the button and recompiling with F6 the button gets resized to 200x100. Why isnt this working when placing?
I mean... the FlowLayoutPanel handles added controls right when you place it. Thats the exact behaviour im looking for.
Using OnControlAdded
To fix your code, when you drop a control on container and you want to set some properties in OnControlAdded you should set properties using BeginInvoke, this way the size of control will change but the size handles don't update. Then to update the designer, you should notify the designer about changing size of the control, using IComponentChangeService.OnComponentChanged.
Following code executes only when you add a control to the container. After that, it respects to the size which you set for the control using size grab handles. It's suitable for initialization at design-time.
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
if (this.IsHandleCreated)
{
base.BeginInvoke(new Action(() =>
{
e.Control.Size = new Size(100, 100);
var svc = this.GetService(typeof(IComponentChangeService))
as IComponentChangeService;
if (svc != null)
svc.OnComponentChanged(e.Control,
TypeDescriptor.GetProperties(e.Control)["Size"], null, null);
}));
}
}
I'm facing the fact that i cannot understand Well how AdornerLayer is added for UIElements.
I have such a situation:
I have a WPF Form which is built with 3 controls:
A Grid on which are 1 Button and 1 TextBox.
In my System, when I click to open this Form, all 3 elements have AdornerLayer not null .
var controls = _frameworkElementProvider.GetUIElements(Content);
var controlsWithAddorner = new List<FrameworkElement>();
foreach (var control in controls) {
var adornerLayer = AdornerLayer.GetAdornerLayer(control);
if (adornerLayer != null) {
controlsWithAddorner.Add(control);
}
}
The collection controlsWithAddorner contains all my 3 controls.
The method GetUIElements(FrameworkElement parent) returns an IEnumerable<FrameworkElement> in which are all controls within a Panel.
I have such a functionality:
Refresh Form Designer. Which recreates the xaml for that Form.
After that Refresh is done, I check the list of controls for AdornerLayer. For all controls the AdornerLayer is null.
The problem is here, I cannot understand where AdornerLayer (s) are lost?
Should I take care To add them forr each UIElement when I Refresh the Designer of the Form?
Please advice me with some suggestions.
Thank you!
EDIT:
I'll show all the solution if other will encounter such problems :)
The mission is: When there is a SelectedControl in designer, keep it selected even a RefreshDesigner is done.
RefreshDesigner functionality recreates the xaml for the whole form.
// Refresh the Designer
private void RefreshDesigner() {
Content = _xamlProvider.ParseXaml(_xaml.ToString());
//Here was the Problem. All visual child elements of the Content wa not updated after xaml recreation.
//By including that call -> solved the problem
Content.UpdateLayout();
}
Firstly: The xaml of the Form is Updated by using the ParseXaml() method from XamlProvider
// in XamlProvider class
public Panel ParseXaml(string xaml) {
var regex = new Regex("<Grid ");
const int first = 1;
xaml = Regex.Replace(xaml, #"xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""", string.Empty);
xaml = Regex.Replace(xaml, #"xml:space=""preserve""", string.Empty);
//...
xaml = Regex.Replace(xaml, "<BindingGroup .*/>", string.Empty);
var content = (Panel)XamlReader.Parse(xaml);
return content;
}
Secondly: Content.UpdateLayout();
Ensures that all visual child elements of this element are properly updated for layout.
MSDN Official source
After that, All elements have AdornelLayer not Null and I'm able to set the Adorner Border for preciosly selected control in designer.
After the Form is Refreshed, call Content.UpdateLayout(); to Ensures that all visual child elements of the Content were properly updated for layout. MSDN official
I would like to display a ToolTip for when the mouse is hovering over a control.
How does one create a tooltip in code, but also in the designer?
Here is your article for doing it with code
private void Form1_Load(object sender, System.EventArgs e)
{
// Create the ToolTip and associate with the Form container.
ToolTip toolTip1 = new ToolTip();
// Set up the delays for the ToolTip.
toolTip1.AutoPopDelay = 5000;
toolTip1.InitialDelay = 1000;
toolTip1.ReshowDelay = 500;
// Force the ToolTip text to be displayed whether or not the form is active.
toolTip1.ShowAlways = true;
// Set up the ToolTip text for the Button and Checkbox.
toolTip1.SetToolTip(this.button1, "My button1");
toolTip1.SetToolTip(this.checkBox1, "My checkBox1");
}
Drag a tooltip control from the toolbox onto your form. You don't really need to give it any properties other than a name. Then, in the properties of the control you wish to have a tooltip on, look for a new property with the name of the tooltip control you just added. It will by default give you a tooltip when the cursor hovers the control.
Add a ToolTip component to your form
Select one of the controls that you want a tool tip for
Open the property grid (F4), in the list you will find a property called "ToolTip on toolTip1" (or something similar). Set the desired tooltip text on that property.
Repeat 2-3 for the other controls
Done.
The trick here is that the ToolTip control is an extender control, which means that it will extend the set of properties for other controls on the form. Behind the scenes this is achieved by generating code like in Svetlozar's answer. There are other controls working in the same manner (such as the HelpProvider).
ToolTip in C# is very easy to add to almost all UI controls. You don't need to add any MouseHover event for this.
This is how to do it-
Add a ToolTip object to your form. One object is enough for the entire form.
ToolTip toolTip = new ToolTip();
Add the control to the tooltip with the desired text.
toolTip.SetToolTip(Button1,"Click here");
I did it this way: Just add the event to any control, set the control's tag, and add a conditional to handle the tooltip for the appropriate control/tag.
private void Info_MouseHover(object sender, EventArgs e)
{
Control senderObject = sender as Control;
string hoveredControl = senderObject.Tag.ToString();
// only instantiate a tooltip if the control's tag contains data
if (hoveredControl != "")
{
ToolTip info = new ToolTip
{
AutomaticDelay = 500
};
string tooltipMessage = string.Empty;
// add all conditionals here to modify message based on the tag
// of the hovered control
if (hoveredControl == "save button")
{
tooltipMessage = "This button will save stuff.";
}
info.SetToolTip(senderObject, tooltipMessage);
}
}
Just subscribe to the control's ToolTipTextNeeded event, and return e.TooltipText, much simpler.