I have started using xaml based icons in my WPF app, but am struggling to find a simple way to store and share them. The icons are DrawingBrushes.
Do I?
A) Store each icon in its own xaml file wrapped in a resource dictionary. This means that I either have to pull in each icon resource every time I want to paint one, or create a standard "icons" dictionary that pulls every xaml file. This seems a pain to have to maintain, and I still have to pull in the icons resource dictionary every time I want to use an icon.
If I did go for this, how do people normally display the icon? Just a Canvas with the brush as the background?
B) Store each icon in its own xaml file as a UserControl. This makes displaying an icon dead easy - just plonk the approprate control in, and its arguably simpler to declare the XML icons namespace at the top of your XAML rather than merging a resource dictionary.
C) Store all icons in one XAML file wrapped in a resource dictionary. One dictionary to merge but without the maintenance of pulling in individual files into that dictionary. Potentially awkward to edit icons though.
D) ....?
How are other people managing their icons?
Related
I'm working on an app, that displayes huge (10000+ elements) graphs in a wpf canvas.
I'd like a feature like in Visual Studio, when you can split the view of an editor (so I can view two distant part of the same graph at the same time).
I have some constraints:
data binding (creating the bindings) of graph elements makes the loading of big graphs very slow, so I'm not using MVVM, the "VM" knows about the view and updates it directly when needed
the children of the canvas are frameworkelements, since I use the Tag property
because of the number of graph elements, I don't want to keep two different view for each element for the two part of the split view
So it should be like displaying multiple parts of the same canvas in different places. You can't set two parents for the FrameworkElements in WPF, so the easiest way is out of question :(
What are my options? Should I reconsider my constraints or there is some workaround for this?
Let me know if you need any more details (it's a big application, so I can't give you every information).
Edit: duplicating with visual brush is not an option since I need proper input event notifications, so both view must be editable.
Options:
Bind the same data to two controls.
Use a visual brush and duplicate input on the real control.
Create a custom graphing control that can output two parts of the graph at once.
If binding to two controls is too slow, then I think you need to rethink your application. The very fact that you have so much data displayed at once that you need a dual view to see separate parts is disturbing. That should raise a red flag. The red flag would notify you that, "What I need, and what I have is different." And you should go back to the drawing board and find out what you really need.
Otherwise, it might be best to create a custom control. The graph is rendering in its entirety even though you only need small portions displayed. If you had your own custom control you could speed up the entire app by rendering only visible portions at a time, and splitting within the control.
I have a WPF application made up of around seven user controls, each with a variety of different controls on each (textbox, combobox, radio button etc).
Across the entire app I have applied a set of control styles take from the WPF Themes on CodePlex, however I have noticed a bit of a slowdown on the app since applying these styles. The ResourceDictionary containing all my styles weighs in at nearly 300kb in code size.
Would there be a benefit to gain by splitting the styles in to multiple Resource Dictionaries and only merging the styles that each usercontrol requires rather than the all the control styles even if they are not being used.
How does WPF load styles in to memory? When required or is the whole ResourceDictionary loaded in to memory at startup?
When an object is created from XAML (or BAML), the XamlReader deserializes all of the XAML's contents. Every XAML element it finds creates an instance of an object - so the Style elements under the UserControl.Resources element generate Style objects that get added to the user control's resource dictionary at the time the object is deserialized. (It's actually a little more complicated than this, since there are apparently parts of XAML deserialization that are asynchronous, but it's close enough for the purposes of this discussion.)
It's important to understand that Resources is not a static property. Every instance of a user control has its own resource dictionary. If you put 300 styles in the user control's XAML, and you create 100 user controls, you'll be creating 30,000 Style objects. This is true whether you're using merged dictionaries or not.
If your resource dictionary is as huge as you say, by far the best thing to do is to put it into the application's Resources property. That way you only pay the price of deserializing each object once.
In order to make a convenient UI for an .Net 2.0 Winforms application I am working on, I have need for a control that I'm pretty sure goes beyond the "out of the box" behavior of any standard control. A mock-up of what I'm trying to achieve follows:
Mock up http://www.claware.com/images/temp/mockup.png
Essentially, this part of the application attempts to parse words into syllables from tribal languages (no dictionary to refer to; any and all unicode characters are possible.) By the time the user gets this far, he has already defined the vowels / consonants in his language and some other configuration. There is then an iterative process of (1) the application guesses which syllables exist in the language based on some rules, (2) the user refines the guesses, selecting the correct parsings or manually parsing a word, (3) the application "learns" from the user's feedback and makes smarter guesses, (4) repeat until the data is "good enough" to move on.
The control needs to present each word (the grey headers), then all the syllable break guesses (the white areas with dots separating the parts of words.) There is also a way to manually enter a parsing, which will display a text area and save button (at the bottom of the mockup.) When the user hovers over a guess, the background changes and "accept / reject" buttons appear. Clicking on the accept, or entering a manual parsing, removes the entire word from the list. Clicking the reject button removes just that item.
I'm by no means 100% sold on the formatting I have above, but I think you can get a general idea of the types of formatting and functional control I need. The control will also scroll vertically--there may be thousands of words initially.
My question for you experienced WinForms developers is: where to start? I would really, really like to stay within the .Net core framework and extend an existing control as opposed to a third-party control. (At the risk of starting a religious war: yes, I suffer from NIH-syndrome, but it's a conscious decision based on a lot of quick-fix solutions but long-term problems with 3rd party controls.) Where can I get the most "bang for my bucK" and the least reinventing the wheel? ListView? ListBox? ScrollableControl? Do I need to go all the way back to Control and paint everything manually? I appreciate any help that could be provided!
[Edit] Thanks everyone for the ideas. It seems like the most elegant solution for my purposes is to create a custom control consisting of a FlowLayoutPanel and a VScrollBar. The FlowLayoutPanel can contain instances of the custom controls used for each word. But the FlowLayoutPanel is virtual, i.e. it only contains those instances which are visible (and some "just out of scroll"). The VScrollBar events determine what needs to be loaded. A bit of code to write, but isn't too bad and seems to work well.
I would look at the TableLayoutPanel and FlowLayoutPanel controls. These will let you organize a series of controls with moderate ease in a vertical fashion. I would then create a UserControl that consists of a label and 2 buttons. The UserControl will expose properties like Text and events that are exposed for the button clicks.. For each entry in the list, you will create an instance of the UserControl, assign the text value, and handle the click events. The instance will be placed in the Table/Flow panel in the correct order. Both of those layout panels do allow for inserting items between other items so you can add/remove items from the list dynamically.
Edit:
Given the length of what you are trying to render, I would consider using the DataGridView and do some custom rendering to make it perform how you want it to work. Using the rendering events of the DGV you can merge columns, change background colors (like highlighting the dark gray lines), turn on/off the buttons, and handle changing the grid into edit mode for your rows to allow modification or inserting of new values. This method would easily handle large datasets and you could bind directly to them very easily.
Well, this certainly looks like a candidate for a custom component that you should be creating yourself. You can create this using standard .Net drawing commands along with a text-box, and a regular button control.
Now you want to find out where to start.
Create a Windows Forms Control Library project.
Drop in the textbox and the button control.
The panel drawing code should preferably be done by code. This can be done using the regular GDI+ commands.
Edit:
Here's another idea, and one that I've practically used in my own project with great success.
You could use a web-browser control in the app, and show your data as html. You could update the source of the web-browser control based on the input in the textbox, and clicking on the links in the web browser control will give you the event that you can trap to do some action. Your CSS will work.
I used this technique to build the 'desktop' in an app I made called 'Correct Accounting Software'. People loved the desktop so much that it is one of the best loved features of the app.
Here's how I would do it:
Create a custom control. In this custom control, have a ListBox atop a LinkButton, and when the LinkButton is clicked you can make it give way to a TextBox. The ListBoxes will have the top row unselectable... you can probably get the rest from there. When you get your list of words, fill a Scrollable of some kind with one control for each word:
(foreach String word in words){
myScrollable.add(new MyComponent(word));
}
From there, I'm not sure what you want to do with the boxes or the data, but that's my initial idea on the UI setup.
Use the WebBrowser control and generate the HTML markup into it using DocumentStream or DocumentText.
I've spent hours working on an application design in WPF and created a whole bunch of different styles along the way. But I noticed that I actually had just edited the styles in the SimpleStyles.xaml file and not a custom dictionary.
So, I started right clicking all controls I could find and selected "edit a copy" and created a copy in a custom resource dictionary. But then I found that alot of the controls are based on several styles. SimpleScrollViewer e.g contains both the thumb and probably more. This created a huge mess in the overall structure of styles in the entire project.
And thus, my question is as follows;
What should I think about when doing this project from scratch again?
Is it best to edit a copy of the SimpleStyles controls? Is there a tool of some sort to manage stuff like this?
Expression Blend will add a resource dictionary for the Simple Styles the first time you use a SimpleStyled control. For real world projects it is best practice to separate resource dictionaries by resource type and then functional area.
For example you will have horizontal resource dictionaries that fall into the following categories:
Brushes
Control Styles
Converters / Selectors
Since these are horizontal their filenames are pretty self-explanatory (e.g. Brushes.xaml, ControlStyles.xaml, Converters.xaml, etc.)
If you are using Silverlight you should probably think about using Themes. In which case you would create Brushes.xaml and ControlStyles.xaml for each [themeName]\generic.xaml you create.
Then you should create resource dictionaries for functional areas that will house the following things:
Item Templates for various ItemsControls used.
Content Templates for various ContentControls used.
One off Control Styles
Each functional area would have a resource dictionary that had the above items (e.g. CustomerManagementStyles.xaml, Orderingstyles.xaml, etc.)
I'm in the process of teaching myself WPF, and I have run into a small issue that I can't find the answer to.
My test app allows image files to be dropped into a StackPanel. Once an image is dropped, a new user control is added to the stack, and displays some meta-data about the file. All is working correctly, and I can iterate through the child controls to retrieve the values.
What I'd prefer to be able to do is allow the user to persist this data to a file, so they can suspend working on the data. The obvious way for me to do this is to store the data in a DataTable and serialise/deserialise it to xml. However, I don't know how to drive the collection of user controls from a DataTable or DataSet object - in fact, I don't even know if this is the right way to go about it in a WPF app. I am more than willing to admit my ignorance here and take better suggestions if there are any.
Summary of the app logic.
1) File is dropped (from Win explorer) onto a StackPanel
2) File triggers creation of a new user control, which is added to the StackPanel
3) Data is populated in the user control
4) Processing data involves iterating through the control collection.
What I'd like
1) File is dropped (from Win explorer) onto a StackPanel
2) File data is inserted into some persistable object (data table?)
3) updated data table drives the generation of the user control to be added to the displayed collection.
4) save / load functionality persists the data for re-use later.
Thanks in advance
You're on the right track with the second approach, what you need to look at is the ItemsControl - that's a thing which can have items added to it. It's the base for ListBox etc, and you can template it to work as you require. Then there's the DataTemplate which handles which controls are displayed and data binding to those controls when an item is added to the underlying data structure. There are quite a few examples around on the net, try Dr WPF.
In order to make everything work the underlying data structure must support change notification. As everything happens automagically, once the Xaml is setup, you can find yourself in an odd situation. You've added data to a data structure, which in turn has caused controls and data to appear in your ItemsControl. How do you link the data items and their visual controls. The answer is to use some built in static methods ItemFromContainer which links from the graphic to your underlying data item, useful to handle click events, and ContainerFromItem which does the reverse.