I have a listbox I'm setting with a datasource of highscores
public class HighScore
{
public string Username {get;set;}
public int Score{get;set}
}
var IList<HighScore> HighScores = getAllTheScores();
MyListbox.ItemsSource = HighScores;
I want to change the background color of any rows which have a Username property equal to the currently logged in user (stored in AppSettings). I've seen Converters but this would need to somehow get hold of the currently logged in user which doesn't seem like something a converter should be responsible for getting.
I could also iterate the listbox items but from what I've seen that's not advised and I should be preferring binding to code behind drilling into controls.
Any suggestions as to how best achieve this much appreciated :)
Two suggestions. You already mentioned the first one, which is to use a ValueConverter. If value value is accessible from a viewmodel (recommended) than that is easy to pass along to the ValueConverter. If it is not stored in a view model then there are no worries with getting this from within the value converter provided it's named properly.
The second suggestion is to use a Behavior. The Behavior would be responsible for setting the background based on the user. I don't see much advantage here over a value converter except for the back that it's not a value converter. It would (almost) do the same thing. Overall I would recommend a value converter. Easy to implement, low code overhead and little xaml needed.
Related
I am working on a custom component, and now I need to add a public property that is visible in properties windows of VS.
This property must be a list of values where the user can choose from. Like a combobox.
I googled around a lot and found this question on SO and tried it, but it seems a lot of work so I wanted a more elegant way. Also, with this code I have no notification when a user chooses an item from the list.
So I found that the proper way of showing a list a user can choose from (on a custom component's properties in the property window of VS) is like the code below
public enum BUTTONSTYLE { Style_Solid, Style_GradientA, Style_GradientB, Style_Image, Style_Liquid };
BUTTONSTYLE _buttonStyle;
[DefaultValue(BUTTONSTYLE.Style_Solid)]
[Category("Appearance")]
[Browsable(true)]
[Description("Sets style of the button")]
public BUTTONSTYLE newbuttonstyle
{
get
{
return _buttonStyle;
}
set
{
_buttonStyle = value;
}
}
While this works very well, my problem is that this needs a enum that is defined and cannot change. In my case the values in BUTTONSTYLE can change. But it's not possible to change the items in an enum. Allthough this answer says it can be done, I tried it and it did not work.
So I am thinking that probably I am doing this a complete wrong way.
How can I add such kind of property to my custom control the proper way ?
For clarity, the property is not a combobox, but should let the user pick a value like if it was a combobox
EDIT
for clarity I will try to explain in other words what my problem is.
I need a property that will present a list to the user, so he can pick an item from this list.
What I found so far is that I should use an enum for this, that will show up in the propertie window as a list (see also the image) where the user can pick from.
But, this is not usefull for me because when I use an enum than the items in the list are defined at designtime and cannot change.
In my case, the items that are presented to the user could change, based on the values of other properties.
So I cannot use an enum after all, so what is the proper way to do this ?
I hope my problem is a bit more clear now
I know when I use Enum and put it as Property for class/UserControl, it will show/display it with drop down list like this:
But is this the only way to display available values like "drop down list"? Do we have other ways to do it?
Edit: The scope is Windows Form Application
For who didn't understand me
In that image(http://i.stack.imgur.com/NMank.png) where wrote "DataBase" is the Name of the Property in design time.
The values: NotChoseYET, ChooseDataBase, ThereAlreadyDataBase are values in Enum I created.
As you can see they displayed in a DropDownList in the design, so I want to ask if there are other ways to display like that without Enum?
Update
After tons of searches, I found what I had answered was only partially correct, so I would like to answer it again.
The answer to your question is a definite NO, we have some other way to show values on property as DropDownList. Like what I mentioned in my old answer, if values come from some kind of Set, or in other word it belongs to a collection of values, it will be displayed as a DropDownList without any extra efforts (because the UITypeEditor has been specified for them, you will understand this point later). Here are 3 examples:
If a Property is a bool, in the designer it will show you a DropDownList contains True and False;
If a Property is a Font.Name, in the designer it will show you a DropDownList with SmallIcon;
if a Property is a Color, in the designer it will show you some DropDownList encapsulated in a TabControl.
From those "native" examples, you may realize a fact: we could somehow use some controls other than a simple DropDownList in the Property Tab during the design time. For example, a Color property gives a TabControl instead of a simple DropDownList, and a Font.Name property gives a customized DropDownList.
Yes, this is the second thing I am going to talk about. You are not only able to customize the items in the DropDownList, but also the View of that Value Choosing Editor.
However, this is very tricky and non-trivial. You are not recommended to do this unless it really adds value to your user control in the design time.
In short, you need to inherit from UITypeEditor, and override 2 functions:
GetEditStyle(), which
indicates to the design environment which kind of user interface your UI type editor implements
and EditValue(), which
establishes the interaction between the design environment and the user interface for editing your custom type
Then for your property which makes use of the Editor, you need to add EditorAttribute to it to specify the Editor used when selecting value of that property.
For better details, you are suggested to check this MSDN walk-through, which explains how to design a customized Value Editor in the design time.
Now back to the point where we left over. The native type, like bool and Color, has already bond to
a UITypeEditor, thus no further working should be done.
Old Answer:
For properties, you need to choose a value from a kind of Set, and all elements in that Set will be displayed as Items in a DropDownList during design time. When you try to define the Set, Enum is one method to define them. Also, you can use set of struct, like Color. In other words, if you have a Property that returns Color (or other structs), during design time it will appear as a drop down list.
You can easily add items to a combobox control by using its .Items property:
private void TestForm_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
// add items to the combobox
// you can use any object. The .ToString() method will be used for displaying it
cbxTest.Items.Add("This is test string " + i);
}
}
This will yield the following form:
I came across this question as I recently needed to do the same.
I posted a question ... which in the end I anwsered myself here.
In a nutshell: Implement a type converter
GetStandardValuesSupported(ITypeDescriptorContext context) to return
true and GetStandardValues(ITypeDescriptorContext context) to return
the StandardValuesCollection for the property type. Finally just
decorate the property like so:
[TypeConverter(typeof(MyClassConverter))]
public MyClass MyProperty { get; set; }
The designer property window will now have a dropdown with valid values.
I'm working on WPF (XAML) using the designer (very newbie) and C# as backing code.
I need to be able to have a few "pages" of Radio Buttons in the same group (i.e. clicking on item A on page 1 then clicking on B on page 2 should deselect A on page 1).
How would I go about doing this?
Thank you!
Note that the "buttons" are actually just radio buttons above images.
First, I would NOT recommend doing this. As a user, I would be very confused/surprised if my selections on one page affected a selection on a previous one.
As to how to accomplish it, I will assume you are using MVVM (as you should be in WPF). First, the ViewModel for each page needs to have a reference to the same backing property in the Model. In other words, your Model has a property like (where MyRadioSelection is some enum you are binding to):
public MyRadioSelection GlobalSelection {get; set;}
and your view models have:
public MyRadioSelection UserSelection
{
get {return Model.GlobalSelection;}
set
{
Model.GlobalSelection = value;
OnPropertyChanged(UserSelection);
}
}
Then you just need a ValueEquals converter (from this answer), bind all your radio buttons to the enum, and you should be good to go!
Please let me know if you would like a piece explained further. Also, posting your existing code would help improve this answer. Also note that your Model may need some way of notifying the ViewModels of external (another ViewModel's) changes to the backing property. You could approach this from several directions, but just implementing INotifyPropertyChanged and listening to it in the ViewModel would work.
I am working on a project which allows tagging of directories. As part of the interface, I would like to display a list of the directories. Each entry in the list would be the directory name, plus a number of columns. One for each tag known to the application at the time, with a checkbox indicating whether the directory has been tagged with that tag or not. The user can then tag or untag a number of directories easily.
I thought using a WPF DataGrid would be good for this, but am having trouble deciding how to store the tagged directory in a way that allows me to bind it to the DataGrid instance easily, since the number & makeup of the tags could change at any time.
One way would be to have a master list of directories & their tags, and from this I could generate a complementary set of Expando objects every time the number of known tags changed. Each object would have a boolean property for each tag. The list of these objects could be bound to the DataGrid and autogenerated columns would display them automatically. The nice thing about this is that it does model what I am displaying nicely - even if the directory doesn't have a tag, it still has the property of "doesn't have this tag", and its simple to implement. The problems are its messy and inefficient, and (not sure about this) I don't think I can call methods on the Expando object when the properties change.
The other way would be to dynamically re-create a DataTemplate whenever the known tags changed. The downside is I have to dynamically create a DataTemplate in code-behind.
I wonder though thinking about the first option - is there a way to override the properties an object appears to have to WPF?
For example, is there an interface like IDataBindingSource which looks something like
interface IDataBindingSource {
string[] MyProperties();
Type[] MyPropertyTypes();
object[] MyPropertyValues();
}
That is, is there a simple way to change what properties appear to the DataGrid (and so use autogenerated columns) at runtime?
EDIT: To clarify about the tags. By tags I mean the small descriptive string version. The number of tags the user will want is limited, but there are a large number of directories. So I would like to display a set of checkboxes for each directory that would allow me to add or remove a tag for that directory, just like you would set permissions for users, for example (each permission being a tag, user's the directory). The number of potential tags at any given time though is variable, as the user could add more, or remove a tag from all directories and effectively deleting it.
This isn't a hard problem - a really naive way would simply be to manually draw a table, one column for the directory, the others with the known list of tags, and then logic would create and set checkboxes in the cells with loops. There are many ways to do it - but I would like to use the nicest - that allows me to code it quickly and preserves functionality inbuilt into controls like freezing and reordering, etc.
I've never been a fan of the DataGrid control, especially not in WPF. Considering how versatile WPF is with control templating and styling, I'd go with the ListView using a GridView as the content (ListView.View).
Then you can scrap the whole convoluted IDataBindingSource bit and go straight MVVM, which is much easier with standard bindings.
For example, you could have a DirectoryModel class that would have something like this:
public sealed class DirectoryModel : INotifyPropertyChanged
{
public ObservableCollection<DirectoryModel> Subdirectories { get; set; }
// Notify when this property changes for proper binding behavior!
public bool IsTagged { get; set; }
}
Then your ListViewItem.IsSelected property would be bound to DirectoryModel.IsTagged.
I have an existing custom control library with controls which may contain properties: HeaderStyle, ModalStyle, Collapsable, etc...
In the user interface the program is currently displaying a categorized list of these properties. I am trying to update this code to hide properties they dont normally use. I have a list of properties to hide/show based on button click but I am not sure how I can hide these fields programmatically.
I would like to retain any values entered into the fields before hiding and re-display the values if the fields are shown again.
Here is a property that current exists but would like to be hidden/shown on toggle.
/// <summary>ModalStyle property for control</summary>
[XmlAttribute]
[DefaultValue(Utility.Common.Enumerations.ModalStyle.None)]
[Category(PropertyCategories.Rendering)]
[Description("Modal dialog style")]
public ModalStyle? ModalStyle
{
get { return control.ModalStyleActive; }
set { control.ModalStyle = value; }
}
My original though was to do some variant on #if DEBUG but use my own Conditional however I was unable to find a way to change my conditionals via button/toggle.
Can anyone please help with a solution to my problem? I have 20-30 controls with 20 to 30 properties that would like to be filtered.
I have two suggestions that, while they may not give you the exact functionality desired, will keep your solution much more straight forward.
First:
Since you are the library developer you should just decide what properties you want other developers to have access to though the IDE properties window. If a property is seldom used or not very useful through the IDE then just place the [Browsable(false)] attribute on it.
Second:
If you really want all properties to be visible in the IDE properties window, but want to give individuals a way of hiding the more advanced (or less used) ones, just throw them all in an 'Advanced' category. The user can then simply collapse that category and forget about them.
Also: Take a look at Oliver's answer to this question:
[how-to-show-or-hide-properties-dynamically-in-the-propertygrid]
I'm not sure to understand what you are trying to achieve.
When you use Attributes, those are static to the class. So, in your case, when you toggle a show/hide on an object, it's on an instance of the object. Also, you cannot change an attribute value at run-time.
Maybe you should try an alternate solution like creating a global
map<pair<type of object, property name>, is shown>
and update that accordingly from your editor.
And if you want to use something like a property grid, you will have a problem since it won't check your map, but it can be fixed. You could create a new class at run-time and make it a proxy to your current instance. (check on the net how to achieve that, but it's quite simple. There are 2 possibilities: compile from a string or use the ILGenerator.
Hope this help.