In my lightswitch app i need to add a small image control to every row, when clicking on it , it should send you to a detail screen. I made the silverlight control and added it to the lightswitch app.
partial void VidContentItemRessources_Loaded(bool succeeded) {
int index = 0;
foreach (VidContentItemRessourcesItem cust in this.VidContentItemRessources) {
this.FindControlInCollection("ImageLinkIcon", this.VidContentItemRessources.ElementAt(index))
.ControlAvailable += (s, e) => {
MyLinkImage = (e.Control as LinkImage);
MyLinkImage.MouseLeftButtonDown += MyLinkImage_MouseLeftButtonDown;
};
index++;
}
}
But if i do this i get an error that the event control available can't be used on controls in collection ..
So i tried to do it like this
LinkImage neco = this.FindControlInCollection("ImageLinkIcon", this.VidContentItemRessources.ElementAt(index)) as LinkImage;
neco.MouseLeftButtonDown += MyLinkImage_MouseLeftButtonDown;
But then neco is allways null because it is trying to load the control before it's available... any solution pls ?
These types of initialisations should go in the screen's Created method, that way you're guaranteed that all of the controls on the screen have been created. If any of the screen's methods (like InitializeDataWorkspace, Created, Saving etc) aren't in your code file, you can create them by using the Write Code dropdown box in the screen editor.
I solved it like this:
I catching click event in silverlight control than i invoking method in lightsiwtch
public void MouseClick(object sender, MouseButtonEventArgs e) {
var objDataContext = (IContentItem)this.DataContext;
var Screen = (Microsoft.LightSwitch.Client.IScreenObject)objDataContext.Screen;
Screen.Details.Dispatcher.BeginInvoke(() => {
Screen.Details.Methods["DoImageLinkEvent"]
.CreateInvocation(null).Execute();
});
}
Related
I've a C# WPF application which show uses Grid control in the xaml(P screen).For every row in the grid, I've a column called Details.Clicking on item in this column shows a pop-up windows which also has a grid in the xaml(C screen).
My item click event in the P's viewmodel has the following code:
var myChildWindow = new MyGridView();
myChildWindow.Show();
If the user clicks on the item multiple times, I just want to highlight the existing C pop-up window.If there's no existing windows open, then only I want to open a new windows.
I've worked on a similar requirement for Winforms applicaiton.How do I go about this for a WPF application please?
Thanks.
First you'd need to declare myChildWindow outside of the click event so that it is accessible from multiple events. So,
MyGridView myChildWindow;
goes outside the click event, probably as a private variable.
Then, in your click event see if it's null, and if it is, create it.
if (myChildWindow == null)
{
myChildWindow = new MyGridView();
myChildWindow.Show();
}
You could keep a reference to the window and get rid of this when the window is closed:
MyGridView myChildWindow;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (myChildWindow == null)
{
myChildWindow = new MyGridView();
myChildWindow.Closed += MyChildWindow_Closed;
myChildWindow.Show();
}
else
{
myChildWindow.Activate();
}
}
private void MyChildWindow_Closed(object sender, EventArgs e)
{
myChildWindow.Closed -= MyChildWindow_Closed;
myChildWindow = null;
}
I have got three forms and on one of them there is a combobox which is supposed to change icons on all my running forms and images of buttons located on another forms, when selected value of the combobox is changed.
Please note that the problem is solved when it comes to changing icons, but I need solution for changing buttons images. I have managed to do so on just one form (where the combobox is located). I cannot figure out how to customise buttons on other forms as well.
I have tried this way:
private void combo_Theme_SelectedValueChanged(object sender, EventArgs e)
{
Main f1 = new Main();
if (combo_Theme.Text == "Purple")
{
foreach (var form in Application.OpenForms.Cast<Form>())
{
form.Icon = Properties.Resources.Purple;
f1.btn_Exit.Image = Properties.Resources.EXIT_purple;
}
}
... but had no success.
Basically, I am stuck now, since the code above doesn't work for me.
Any ideas?
You should re-design your forms by implementing some interface with some method, calling that method will actually update the images of the buttons on a specific form. That way you don't have to loop through each controls (in nested relationship) and check out every button. However if your forms don't have complex nested relationship and the number of buttons is small, we can use the following code, in fact this code still works OK (responsive enough) when you have thousands of controls on a form with several nested containers):
public IEnumerable<Button> GetAllButtons(Form form){
Stack<Control> controls = new Stack<Control>();
controls.Push(form);
while(controls.Count > 0){
var control = controls.Pop();
foreach(var c in control.Controls){
if(c is Button) yield return c;
controls.Push(c);
}
}
}
//now use that method in your code like this:
private void combo_Theme_SelectedValueChanged(object sender, EventArgs e)
{
Main f1 = new Main();
if (combo_Theme.Text == "Purple")
{
foreach (var form in Application.OpenForms.Cast<Form>())
{
form.Icon = Properties.Resources.Purple;
f1.btn_Exit.Image = Properties.Resources.EXIT_purple;
//looping through each button on the current form
foreach(var button in GetAllButtons(form)){
//your code here
button.Image = Properties.Resources.EXIT_purple;
}
}
}
//...
}
I want to use a wheel to change (for example) 30 buttons' background image each time a form loads.
I cannot use this:
for(int i=1;i<=30;i++)
{
button i .backgroundimage=image.fromfile("URL");
}
What should I do?
There are many possible interpretations of your problem. Why can't you use your code? There are also different solutions for your problem.
As example:
public Form1() // Constructor
{
InitializeComponent(); // Ensure all controls are created.
List<Button> buttons = new List<Button>(30);
buttons.Add(mybutton1)
buttons.Add(mybutton2)
// Go futher with all your buttons.
}
private void Form1_Load(object sender, System.EventArgs e) // Create a load event
{
foreach(Button button in buttons)
{
button.BackgroundImage = Image.FromFile(path);
// Note: The file remains locked until the Image is disposed!
}
}
Well you could use something like this assuming this code executes in a Form_Load and the buttons Parent control is your form. Have in mind that you should supply the real path to your image that you want to set as a background image
string path = "rootNameOfTheImage";
int counter = 0;
foreach(Control ctrl in this.Controls)
{
if(ctrl is Button)
{
Button btn = (Button)ctrl;
if(/* test if this button should be used */)
{
btn.BackgroundImage=Image.FromFile(path + counter++.ToString() + ".jpg");
}
}
}
Say I have a Form which we'll call it ParentForm, and it contains a Panel which we'll call ContainerPanel. Now, ContainerPanel contains a Panel, which we'll call EntityPanel.
So basically, the Form contains A Panel which contains a Panel.
In ContainerPanel, we have:
void EntityPanel_MouseDown(object sender, MouseEventArgs e)
{
ContainerPanel.Controls.Remove(EntityPanel);
ParentForm.AcceptEntityPanel(EntityPanel);
}
and in MainForm, we have:
void AcceptEntityPanel(Panel panel)
{
Controls.Add(panel);
panel.MouseUp += new MouseEventHandler(
delegate(object sender, MouseEventArgs e)
{
MessageBox.Show("Mouse has been released.");
});
}
Note: This is example code only, which I have just typed in here without verifying syntax, etc. I realise it is trivial to combine these two functions into one, however in my application these two functions do several other things and should be separate.
So the EntityPanel, which belongs to ContainerPanel needs to be transferred to ParentForm when the user presses the mouse down.
When the user releases the mouse, I still need the MouseUp event to be triggered, but it is not working.
Previously, I was passing information about the panel and creating a new panel on the parent form, and manually calling the MouseDown method.
What I'm doing now, as you can see in my above example, is that I'm passing the exact same panel back to the parent form. I had hoped that this way the MouseDown/MouseUp would work, however it didn't.
I'm running out of ideas on how else to structure this module of my program.
Any ideas?
This works for me:
void Form1_Load(object sender, EventArgs e)
{
var innerPanel = new Panel();
outerPanel.Controls.Add(innerPanel);
innerPanel.MouseDown += (a,b) =>
{
outerPanel.Controls.Remove(innerPanel);
Controls.Add(innerPanel);
innerPanel.MouseUp += (x,y) => MessageBox.Show("!");
};
}
I have a windows form with a panel on the left, which consists purely of radiobuttons, and a tabcontrol in the middle, with multiple tab pages within it. Each of these individual tabpages have a series of datagridviews within it, which are shown and hidden depending on which radio button you check.
I accomplish this effect by having each of the radiobuttons on the left assigned a CheckChanged event, which loops through all of the controls within the tabpagecontrol.SelectedTab, and calls .Show() on the corresponding datagridview and calls .Hide() on the rest so that only one datagridview is visible at one time.
My problem occurs when i try to programmatically check one of these RadioButtons. Lets say in Method X, I write RadioButtonA.checked = true. This triggers the usual CheckedChange event handling, which loops through all the datagridviews on the currently selected tabpage and calls .Hide() on everything except the one datagridview form that the radiobutton is supposed to bring up and calls .Show() instead. However, on one of these .Hide() calls on the datagridview, it ends up triggering the RadioButtonA.CheckedChange event AGAIN for a second time. When i look at the sender argument passed to the function, it shows that the sender is the RadioButton i just programmatically clicked on.
I am adding these datagridviews programmatically and can confirm that there are no eventhandlers assigned whatsoever to them. Can anyone help me determine what is causing this additional event to get triggered? Thanks.
For obnoxious change events that trickle through and upset other event handlers on my forms, I've found the only solution is to add a small boolean value:
bool radioIng;
void MyMethod() {
radioIng = true;
try {
radioButton1.Checked = true;
// etc.
} finally {
radioIng = false;
}
}
void radioButton_EventHandler(object sender, EventArgs e) {
if (radioIng) return;
// rest of code here
}
EDIT:
Alternately, you could just remove all of your event handlers and reconnect them later:
void MyMethod() {
try {
radioButton1.CheckChanged -= radioButton_EventHandler;
radioButton2.CheckChanged -= radioButton_EventHandler;
radioButton3.CheckChanged -= radioButton_EventHandler;
// execute your code
radioButton1.Checked = true;
} finally {
radioButton1.CheckedChanged += new EventHandler(radioButton_EventHandler);
radioButton2.CheckedChanged += new EventHandler(radioButton_EventHandler);
radioButton3.CheckedChanged += new EventHandler(radioButton_EventHandler);
}
}
void radioButton_EventHandler(object sender, EventArgs e) {
if (sender == radioButton1) {
// code here to handle
} else if (sender == radioButton2) {
// code here to handle
} else if (sender == radioButton3) {
// code here to handle
}
}