Get resourcename of PictureboxImage - c#

I've got a Picturebox, the user can select its backgroundimage out of a resource file.
Later I want to get the resourcename out of the picturebox.
I've already tried this:
MessageBox.Show(((PictureBox)sender).BackgroundImage.ToString());
But it gave me the format of the picture.. there isnt something like:
MessageBox.Show(((PictureBox)sender).BackgroundImage.Name.ToString());
and I've already thougt about setting a Tag to the Picturebox with the picturename when setting the Image... but this is annoying as hell...
So how can I get the name of the Resource used as the backgroundimage at a Picturebox easily?
I think i have to explain the whole situation:
Ive got a form with a lot of raidbuttons...
if you select one of those buttons and click on a panel,the panel changes to the selected radiobuttonimage...
the click event of the panel:
PanelClick(object obj ,...)
{
if(radiobuttonApple.checked)
{
obj.backgroundimage = resource.apple;
}
if(radiobuttonPear.checked)
{
obj.backgroundimage = resource.Pear;
}
}
and hundred more of those...
and later on i want to know wich resourcefile the backgroundimage is..
Isnt there something like this:
(if i would name the radiobuttons like the resources)
PanelClick(object obj ,...)
{
obj.backgroundimage = resource[selectedradiobutton.Name]
obj.tag = selectedradiobutton.Name
}
So now im about to use LINQ:
RadioButton checkedRadioButton = panel1.Controls.OfType<RadioButton>().FirstOrDefault(r => r.Checked);
obj.tag = checkedRadioButton.Text;
so i only need to know how to get a resource dinamical by name e.g.:
obj.backgroundimage = resource[checkedRadioButton.Text];
and ill use a resourcemanager :
var resman = new System.Resources.ResourceManager(
"RootNamespace.Pictures",
System.Reflection.Assembly.GetExecutingAssembly()
)
var image = resman.GetPicture("checkedRadioButton.Text");
i hope this will work ..

Create a method to return the resource based on the selected radio button.
Example:
private resource checkResource()
{
if(radiobuttonApple.checked)
{
return resource.apple;
}
if(radiobuttonPear.checked)
{
return resource.Pear;
}
}
Then you can use it like this:
PanelClick(object obj ,...)
{
obj.backgroundimage = checkResource();
}
or
PanelClick(object obj ,...)
{
obj.backgroundimage = checkResource();
obj.tag = selectedradiobutton.Name
}
EDIT:
As you said, this approach can have different problems based on the number of iterations for each assignment. To avoid this and also in the light of another solution, you can use a single event to handle all the radio button state changes like this:
First, create a resource variable to be assigned to whenever a radioButton's status changes. ie.
private Resource bgResource;
private void radioButton_CheckedChanged(object sender, EventArgs e)
{
RadioButton obj = sender as RadioButton;
bgResource = resman.GetPicture(obj.Tag);
}
Then any time you want to change background you can simply say:
obj.BackgroundImage = bgResource;

Related

Reset part of application settings

So, I have Form called Preferences with TabControl in it. This TabControl contains several TabPages(General, Advanced, Misc, ...) with few comboboxes, checkboxes and labels. Each of this control inside TabPage is assigned Application Settings Property Binding (aka they show saved user settings, user can change them etc...).
I know that there is a method to reset all settings (Properties.Settings.Default.Reset();), but is there a way how to reset only settings inside one TabPage?
My solution is to iterate thru controls in TabPage, check if it is combobox, label etc and then reset it´s value to default, but is there a "oneliner" solution to this ?
Use the following solution to get the original value of a single setting:
(The example assumes you want to get the ORIGINAL value of a setting named 'Username')
var defaultUsername = Properties.Settings.Default.GetType()
.GetProperty(nameof(Properties.Settings.Default.Username))
.GetCustomAttribute<System.Configuration.DefaultSettingValueAttribute>()
.Value;
Important - this solution will always return a string value. make sure to parse it properly, or use this extension method I wrote:
public static T GetDefaultValue<T>(this ApplicationSettingsBase settings, string settingKey)
{
return (T)Convert.ChangeType(settings.GetType()
.GetProperty(settingsKey)
.GetCustomAttribute<DefaultSettingValueAttribute>()
.Value, typeof(T));
}
Usage:
var defaultNumber = Properties.Settings.Default.GetDefaultValue<int>(nameof(Properties.Settings.Default.Number));
The ApplicationSettings doesn't have built-in support to reset just some properties. But to solve the problem, you can use either of these options:
Create a method which resets all bound controls of a TabPage
Using Multiple Settings Files with Designer Support
Option 1 - Create a method which resets all bound controls of a TabPage
You can create a method which look at controls of the tab page and check if it's bound to application settings, find the property in settings and reset its value to the default value. Then you can reset settings of a TebPage width one line of code: ResetSettings(tabPage1);.
Here is the method:
private void ResetSettings(TabPage tabPage)
{
foreach (Control c in tabPage.Controls)
{
foreach (Binding b in c.DataBindings)
{
if (b.DataSource is ApplicationSettingsBase)
{
var settings = (ApplicationSettingsBase)b.DataSource;
var key = b.BindingMemberInfo.BindingField;
var property = settings.Properties[key];
var defaultValue = property.DefaultValue;
var type = property.PropertyType;
var value = TypeDescriptor.GetConverter(type).ConvertFrom(defaultValue);
settings[key] = value;
//You can also save settings
settings.Save();
}
}
}
}
Option 2 - Using Multiple Settings Files with Designer Support
If the reason of using a single settings file is because of designer support, you should know you can have designer support also with multiple settings files. Then you can use different settings files and reset each settings group separately. You can simply encapsulate them in a single class using such code:
public static class MySettings
{
public static Sample.General General
{
get { return Sample.General.Default; }
}
public static Sample.Advanced Advanced
{
get { return Sample.Advanced.Default; }
}
public static void ResetAll()
{
General.Reset();
Advanced.Reset();
}
public static void SaveAll()
{
General.Save();
Advanced.Save();
}
}
To reset a setting group it's enough to call MySettings.General.Reset();
To reset all settings, you can call MySettings.ResetAll();
Note for design-time support
To have designer support for binding properties to settings, create multiple settings files in root of your project. Don't put settings files in folders. The setting picker, only shows Settings.settings file which is in Properties folder and those files which are in root of project. This way you can see different settings files and settings properties in a tree-view like this:
TabPage page = aTabControl.SelectedTab;
var controls = page.Controls;
foreach (var control in controls)
{
//do stuff
}
Try this:
private void button2_Click(object sender, EventArgs e)
{
TabPage page = tabControl1.SelectedTab;
var controls = page.Controls;
foreach (var control in controls)
{
if(control is TextBox)
{
//do stuff
}
if(control is ComboBox )
{
ComboBox comboBox = (ComboBox)control;
if (comboBox.Items.Count > 0)
comboBox.SelectedIndex = 0;
comboBox.Text = string.Empty;
}
}
}

Win 8.1 SearchBox SuggestionsRequested

I got an userControl that contains a searchBox.
This UserControl is inside another one.
I got a strange behavior while i'm searching, because the suggestionCollection works in a strange way.
Example :
in the searchBox i write something all works perfectly, if i choose the item it also works.
But if i try to use backspace (after the choose) i got no suggestion.
I cannot understand why it doesn't work.
That's the code
//var deferral = args.Request.GetDeferral(); //it seems to not influence the behavior
var suggestionCollection = args.Request.SearchSuggestionCollection;
try
{
TransporterExt tr_search = new TransporterExt();
//queryText is a string inserted in the searchBox
if (string.IsNullOrEmpty(queryText)) return;
tr_search.name = queryText;
suggested.Clear(); //that's a collection..
//just a search that return a collection of objects TransporterExt
querySuggestions = await TransporterService.Search_StartsWith(tr_search);
if (querySuggestions.Count > 0)
{
int i = 0;
foreach (TransporterExt tr in querySuggestions)
{
string name = tr.name;
string detail = tr.trId.ToString();
string tag = i.ToString();
string imageAlternate = "imgDesc";
suggestionCollection.AppendResultSuggestion(name, detail, tag, imgRef, imageAlternate);
this.suggested.Add(tr);
i++;
}
}
}
catch (System.ArgumentException exc)
{
//Ignore any exceptions that occur trying to find search suggestions.
Debug.WriteLine(exc.Message);
Debug.WriteLine(exc.StackTrace);
}
//deferralComplete(); //it seems to not influence the behavior
The problem is that: all the variables have the right value, but the suggestion panel appears only if i make a particular search: it appears when i change the first letter of search, or after an wrong seach
What appends when i make a search
What appends if i use the backspace, and i what i want to fix
As i said, all works perfectly, after the "backspace" action the suggestionCollection got the right value...but the panel is missing.
Could someone help me?
You can use SearchBox and SuggestionRequested event to fire the event when type on the SearchBox. I will show an Example
<SearchBox x:Name="SearchBoxSuggestions" SuggestionsRequested="SearchBoxEventsSuggestionsRequested"/>
and write the SearchBoxEventsSuggestionsRequested handler in the code behind
private void SearchBoxEventsSuggestionsRequested(object sender, SearchBoxSuggestionsRequestedEventArgs e)
{
string queryText = e.QueryText;
if (!string.IsNullOrEmpty(queryText))
{
Windows.ApplicationModel.Search.SearchSuggestionCollection suggestionCollection = e.Request.SearchSuggestionCollection;
foreach (string suggestion in SuggestionList)
{
if (suggestion.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase))
{
suggestionCollection.AppendQuerySuggestion(suggestion);
}
}
}
}
You can add the keyword to SuggestioList, and it will show in the dropdown when you type on the Searchbox.
Create the SuggestionList
public List<string> SuggestionList { get; set; }
initialize the list
SuggestionList = new List<string>();
and add keywords to the list
SuggestionList.Add("suggestion1");
SuggestionList.Add("suggestion2");
SuggestionList.Add("suggestion3");
SuggestionList.Add("suggestion4");
SuggestionList.Add("Fruits");
Thanks.

Declaring a new object via variable name

I'm fairly new to C# (and programming in general) so stick with me if I make any huge errors or talk complete bull.
So what I'm trying to do is have a private void that resizes the background image of a button. I send the name of the button to the private void via a string. Anyway, the code looks something like this:
ButtonResize("Zwaard");
protected void ButtonResize(string Button)
{
string ButNaam = "btn" + Button;
Button Butnaam = new Button();
Butnaam.Text = ButNaam;
if (Butnaam.BackgroundImage == null)
{
return;
}
else
{
var bm = new Bitmap(Butnaam.BackgroundImage, new Size(Butnaam.Width, Butnaam.Height));
Butnaam.BackgroundImage = bm;
}
}
But it doesn't work like that. I can't seem to find a way to declare a new object named the value I have in a string. What I want my code to do is instead of making a button called "Butnaam", I want it to create a button called btnZwaard (the value of the string Butnaam).
How do I tell C# I want the value of the variable to be the name of a new button, not literally what I type?
Thanks in advance.
Are you looking for something like this? By passing the Button to the method you can then act on the object. If this is what you are looking for then you should read Passing Reference-Type Parameters
protected void ButtonResize(Button button)
{
if (button != null && button.BackgroundImage != null)
{
button.BackgroundImage = new Bitmap(button.BackgroundImage, new Size(newWidth, newHeight));
}
}
A string is a piece of text. You subsequently refer to it as a class, which is wrong. Assuming it were right you create a new button rather than "resize its image".
What you want to do to get you started is create a new function in the same class as the dialog that has the button. That function can resize the image of the control.
Edit: this doesn't seem like a good starting point for learning a language, btw. Please find a good online tutorial for starting in C# (e.g. a hello world application).

Is it possible in MonoTouch to determine if the user clicked on an image in a BadgeElement?

I have amended the TODO list app to use a badge element instead of the boolean element as follows:
protected void PopulateTable()
{
tasks = TaskManager.GetTasks().ToList ();
UIImage ticked = new UIImage("checkbox_checked.png");
UIImage unticked = UIImage.FromFile("checkbox_unchecked.png");
Root = new RootElement("Tasky") {
new Section() {
from t in tasks
select (Element) new BadgeElement(t.Completed ? ticked : unticked, (t.Name==""?"<new task>":t.Name), delegate {
Console.WriteLine("???");
})
}
};
}
Is it possible to check to see if the user has clicked an icon rather than the text, and change the behaviour? Essentially I want to do this...
var task = tasks[indexPath.Row];
if(clickedIcon) {
currentTask = task;
task.Completed = !task.Completed;
TaskManager.SaveTask(currentTask);
} else {
ShowTaskDetails(task);
}
But I don't see any parameters inside IndexPath that allow me to access the column or the tapped element.
Any ideas
You need to create a custom version of the BadgeElement, and basically raise an event for the image that is separate from raising an event for the text.
Luckily for you, the whole source code is available, so you can just copy/paste BadgeElement, rename it, create a new unique key and modify it.

c# - use variables from different methods

Im not sure im going about this the right way or not, so hopefully somebody can help me.
Im trying to use a var in a method, which is contained in a different method. As expected, I get the error: The name 'Title1' does not exist in the current context .
first im reading an xml file then populating bing maps with pushpins. One of the variables is the tite of each xml item, I need to use the "Title1" var on my method below.
Here is the code:
public void OnOpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
var document = XDocument.Load(e.Result);
if (document.Root == null)
return;
var xmlns = XNamespace.Get("http://www.blahblah.com");
var events = from ev in document.Descendants("item")
select new
{
Latitude = Convert.ToDouble(ev.Element(xmlns + "Point").Element(xmlns + "lat").Value),
Longitude = Convert.ToDouble(ev.Element(xmlns + "Point").Element(xmlns + "long").Value),
Title = (ev.Element("title").Value),
Description = (ev.Element("description").Value),
Link = (ev.Element("link").Value),
};
QuakeLayer.Children.Clear();
foreach (var ev in events)
{
var accentBrush = (Brush)Application.Current.Resources["PhoneAccentBrush"];
var Title1 = (ev.Title);
var pin = new Pushpin
{
Location = new GeoCoordinate
{
Latitude = ev.Latitude,
Longitude = ev.Longitude
},
Background = accentBrush,
Content = Title1
};
QuakeLayer.AddChild(pin, pin.Location);
}
}
public void Pushpin_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
NavigationService.Navigate(new Uri("/blahblah.xaml?info=" + Title1, UriKind.Relative));
}
If you use an anonymous method inside your loop you will be able to access this variable (magic happens during compilation):
var pin = new Pushpin
{
...
Content = Title1
};
pin.ManipulationStarted += (s, a) =>
{
// Code for the event here
// ... do something with Title1
};
QuakeLayer.AddChild(pin, pin.Location);
Is the PushPin the sender of the event? If so, you can get the title from it since you set that as it's content.
public void Pushpin_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
var pushPin = (PushPin)sender;
var title = pushPin.Content;
NavigationService.Navigate(new Uri("/blahblah.xaml?info=" + title, UriKind.Relative));
}
You can't reference local variables across different methods. For one thing, the local variable no longer exists when the function it's defined in returns. For another thing, it looks like the Title local variable will be assigned a lot of different values over the course of running through the events foreach loop, so moving the Title1 variable out to a class field won't solve anything.
Your best bet is probably to associate the Title1 with the pushpin object. What object is passed into your pushpin event as the sender? If that's the pushpin object itself, or the pushpin object is available via the event args parameter, then you're home free. The pushpin's Content property contains the Title1 value. Use Pushpin.Content instead of Title1.
Make it a class variable. Or pass it as an argument to another function. But the local variable is only valid inside a function. (A function can be called many times recursively. In that case, there are multiple copies of all the local variables in each stack frame. So what you're asking makes no sense.)
Since Title1 is created inside of a loop the only real "viable" method is for you to pass the item as a parameter to the object, OR to store he value that you need in a location that you could get it from. (Possibly as a Tag on the object that starts your other event).

Categories