It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I'd like to create a WPF application and would like some advice on the most appropriate approach.
I want to create an RSS reader that automatically refreshes when a new RSS entry is added. The problem is that I don't want to use traditional controls (listbox/listview) to display the data. I'd like the feed items to appear in panels randomly on the screen. These panels consist of several textblocks. Each panel displays one feed item.
It would look something like this:
Concept
This raises several questions:
1: Generate panels completely from code, or use a Custom Control?
I would model a class like a panel as described above. This class manually adds all controls to the form and drops the panel at a random location on the form. When a new RSS entry is added, an instance of this class gets instantiated and passes the rss information as parameters.
On the other hand, it might be better to create an UserControl for this. Is it easy to create this UserControl by code and pass it the parameters in the constructor?
2: Can my data/panel automatically update when a new RSS entry has been added online?
Right now I would refresh everything each (x) seconds and check against a collection of panels if there has to be created a new one. If so, create a new panel and drop it randomly on the form.
Is there a better way of doing this? I can use a local ObservableCollection with databinding that automatically updates a control (listbox, etc) when the collection changes, can this also be done with an online source like an RSS feed?
The most ideal way would be that my application gets notified when a new RSS entry has been added, downloads the last entry and creates a new Panel (trough code or trough a UserControl)
If this is hard thing to accomplish, I'll use the traditional refresh method.
3: Do I have to use DependencyObject/DependencyProperty?
I know DependencyObject & DependencyProperty expose some powerful functionality for UserControls, but I don't really know how to use them. Are they necessary for this kind of application?
4: Do I have to use WCF (Windows Communication Foundation)?
I'm not really experienced with "advanced" WPF stuff like advanced databindings, DependencyObjects and UserControls, but I love to learn!
I would recommend firstly looking into using the MVVM design pattern, and using an MVVM framework. Secondly, you could achieve this effect using an ItemsControl and use a Canvas as it's ItemsPanel type, then you could use a custom ItemTemplate which renders each data object using a UserControl.
The user control would have a dependency property which is the data item, and you would bind this in the item template declaration.
You could have a model which models each RSS entry (RSSEntry) and perhaps an RSSEntryViewModel which adds the x and y coordinates on the canvas.
Your screen view model would then have an ObservableCollection of RSSViewModel which you would add/delete etc to and the UI would automatically update.
You wouldn't need a service layer if you didnt want to, but as long as your view model retrieves the entries via an abstraction, it should be easy to refactor in the future.
Generate panels completely from code, or use a Custom Control? I usually try to do as much as I can in XAML declaratively, separating logic and presentation usually helps scalability of the application and code quality - but of course there are limits. UserControls generally are not supposed to have parameters in their constructors (not that they can't have them, but you have to have a parameterless constructor so the class can be instantiated from XAML).
Can my data/panel automatically update when a new RSS entry has been added online? There has to be something to send update notifications to the WPF layer, so it can update the display. In case of a RSS application, I guess you will have to manually periodically scan the RSS channels for updates (RSS is a pull technology) and in case of update add the item into the ObservableCollection which will send the appropriate update notification for you.
Do I have to use DependencyObject/DependencyProperty? No, you can use INotifyPropertyChanged. DependencyProperties are generally used in properties which will serve as binding target (the property that is declaring the binding) or in properties that will take advantage of any other DP feature - value inheritance or animation. INotifyPropertyChanged is enough for the properties that are bound to (that are named in the binding expression). Note that you can use NotifyPropertyWeaver to generate the notifications for INotifyPropertyChanged automatically - you just create the OnPropetyChanged method and the weaver will then call it whenever any property of the object is changed! And it even integrates beautifully with Visual Studio.
Do I have to use WCF (Windows Communication Foundation)? For WCF you have to have something to communicate with - it is a communication framework after all. Do you?
You should use a WPF listview (or similar; not sure which control exactly), and theme it to match your desired "panel" idea. That is one of the great strengths of WPF. Then you get all the benefits of the built-in control, with any look you want.
Bind to the ObservableCollection; how you update that observable collection is your business. I don't think RSS has a "push notifications" part of its spec, so polling is how these things are usually done. But in the end it doesn't really matter; that part of your code is completely separate from WPF, so as long as it updates the ObservableCollection, you're good.
Either DependencyObject/DependencyProperty or INotifyPropertyChanged are generally necessary for any kind of WPF application with databinding. It's worth learning them, and then maybe learning a framework that abstracts them away for you.
No; WCF has nothing to do with WPF. You can use any technology to talk to the server that you like.
1: Generate panels completely from code, or use a Custom Control?
Create two view model classes. One class will model the view of all your items, and one representing the content of a single item. The former will contain an observable collection of the latter.
Build a user control to display each.
The container view will be an ItemsControl whose ItemsSource is bound to its collection of item view models, whose ItemsPanel is a Canvas, and whose ItemContainerStyle binds Canvas.Top and Canvas.Left properties to Top and Left properties in the item view models. When a new item is added to the view model's collection, binding will automatically create a new panel for it.
The item view models will generate the random values of Top and Left themselves. (You could also have them request the values from the container when they're constructed.)
(If the term "view model" doesn't mean anything to you, you need to research the model/view/view model pattern, aka MVVM.)
2: Can my data/panel automatically update when a new RSS entry has been added online?
First off, you need to research how RSS aggregators work, since you're writing one. That will explain to you the mechanics of getting updates from RSS feeds. That problem is completely distinct from the problem of presenting the updates once you get them.
Your RSS aggregation layer will check feeds, look for new items, and when it finds new items, raise an event. Your UI layer will handle events raised by the aggregation layer and create new view model objects for every new item received.
This use of events completely decouples the two components from each other. For instance, you can test your UI by building a mock aggregator that generates test messages and having your UI listen to it instead of your real aggregator. Similarly, you can test your aggregator without building the - you can just build a listener that registers for its events and dumps items to the console.
3: Do I have to use DependencyObject/DependencyProperty?
You probably won't don't have to implement your own, no.
4: Do I have to use WCF (Windows Communication Foundation)?
Why wouldn't you?
Related
I have a list of custom controls that should look something like this
Before I start to implement them through a custom or user control in WPF (via MVVM), I want to ask if I do everything right. I create a DataTemplate and binding properties I need (these are the numeric values (0.13) in columns) and ItemTemplat'ing it to listview or listbox. Also I'm having an observable collection of viewmodels for these templates and every viewmodel sends some specific numeric data through short intervals from slave device. Also I need this green element to be clicked (just to add a button to a template I guess) and having displayed an additonal window with real time plots. So my question is: Is this the right approach I'm talking about or do I have something wrong? I'm quite new to WPF, so please excuse me. I dont think that it is a great challenge to implement something like this.
I'm rather new to this model as well, however one thing I have found that has helped me with managing multiple View Models has been an IOC Locator. An example can be found here:
http://dotnetpattern.com/mvvm-light-toolkit-example
I have two ObservableCollections in my ViewModel. Both of same generic type.
Window has two ItemsControls each with ItemsSource bound on its own ObservableCollection from ViewModel.
Both use same same ItemTemplate. This ItemTemplate is very complex user control.
It's all done by the book.
In some cases, I move item from one collection to another. UI updates correctly. However, as control is complex, it needs about 1-2sec to render when it is recreated in new ItemsControl. And since this happens on drag and drop operation, it is not user friendly.
What I would like to do is to somehow preserve existing instance of ItemTemplate from source ItemsControl and reuse it in destination. I don't know if it is even possible, I couldn't find anything about it online.
I believe setup is fairly simple, but if needed I'll write some simplified version of code (I can't share the real code).
Thanks for any help.
What I would like to do is to somehow preserve existing instance of ItemTemplate from source ItemsControl and reuse it in destination. I don't know if it is even possible, I couldn't find anything about it online.
I am afraid it is not. When you disconnect an element from the visual tree and then add it back to a different parent element at a later stage, all elements that make up the control will be re-rendered.
Ok, this is going to be a 1000ft long question, but there's a lot to cover so here goes:
I am creating a paged items control, the purpose of which is to display very large collections in a paged format. I've created a repository on GitHub which can be found here. I have removed any styling for simplicity.
Upon starting the application, it looks like this:
This is pretty straightforward really, there's navigation buttons, an items per page selector but that isn't really important. The problem here is when you click the button "Open New Window".
This will open a new MainWindow, but on the first window, the collection disappears, as shown below:
The image above shows the old window in front, as you can see, there is no list of content as there is on the new window.
So, after smashing my head against a wall for a couple of hours, I am in need of assistance. I'll provide an overview of how the project is structured.
AnagramPagedItemsControl
The control being used for displaying the content is a custom control called AnagramPagedItemsControl, it is responsible for handling navigation between pages. I think the key property here is the PagedCollection.
The PagedCollection dependency property holds the collection which is bound to the Models property in the TestItemsViewModel.
TestItemsViewModel
This is the DataContext of the MainWindow, each window instance should create it's own view model. The CreateTestItems() method is responsible for creating the list of test items.
LazyPagedCollection
The purpose of this collection is to encapsulate the logic of a paged observable collection, it only loads pages when they are needed, hence the laziness.
It exposes methods like NextPage which are called in the AnagramPagedItemsControl when the user clicks on the various navigation buttons. The view model can also call navigation on the LazyPagedCollection, this allows the view model to call navigation without having to go through the view to do it.
TL;DR
When I create a new Window, the content of the previous window disappears. The problem is almost certainly with the control however I am stuck as to how to fix the problem.
This is quite a large problem to look at so I'd be very grateful for anyone who can look into it. Again, the source code is here, please feel free to suggest alternatives or pick out anything that I may have overlooked.
Had some time to spare, so:
The problem is the setter for the CollectionView property in the style for AnagramPagedItemsControl in generic.xaml.
This does not instantiate a new ListBox every time the style is applied; it will just create the one ListBox, the first time the style is created, and use that value over, and over again. So in effect, every instance of MainWindow shares the same ListBox.
You can see this by setting the Tag property of PART_CollectionView to (for instance) "1" in SetupBindings(ItemsControl PART_CollectionView). When you open a new window, you'll see that PART_CollectionView.Tag contains the same value you previously assigned.
I'm trying to make something like a quiz application where 3 questions will be brought up on screen at a time, allowing the user the check a radio button containing "Yes" or "No", and have an answer come up appropriately to his response. The questions will continually come from a database I'm using.
After a few attempts I've figured that using x:Name property is not a great solution, since it doesn't allow me to use a loop in order to change the questions and answers. Is there any other way to make a grid with the same types of objects in each cell, being able to access each object inside each cell of the grid in the code-behind?
Here is list of steps you need to implement,
Need to create QuestionModel, contains question properties, make sure your model inherits INotifyPropertyChanged.
Need to create ViewModel, which contains data objects, public/dependency properties
Need to bind/set data objects/properties on viewmodel constructor
Need to set your ViewModel as a DataContext of your View(.xaml) (You can create this on zammel directly and codebehind as well
Need to bind your UI objects like Question/answers/yes-no with viewmodel properties accordingly
WPF/Silverlight has their own fundamentals like Data Binding, Resources, Compiler, Dependency Properties. Above steps comprises MVVM design pattern. During each steps, please google for specific stuff.
I'm currently writing a WPF progress bar that includes a rate (see Windows 8 - Fancy Progress Bars API?).
The screenshot below shows what I've got so far (left) and a badly done all in code as part of my learning exercise (right). I'm now trying to convert the code version to use as much XAML as possible.
I've got most of the way there by creating a new class called RateBase and implementing it in a similar way to RangeBase. I've then added a new instance and provided a template file RangeGraph. I'm attempting to do this as by the book as possible, but I'm not sure how to tackle the final stage.
I now wish to add a graph, this graph is to display the rate as it has changed historically as the progress has progressed. I have 'Rate' as a value I can bind to, but I believe somwhere I need a Double[] containing my historical rate values. My question is where should this be placed (I don't really want to pollute RateBase) and how do I bind to it from my template (I don't believe I can bind to RangeGraph.cs if I add properties on there or am I wrong?)
You are right, you will need historical Data. In my opinion, whenever the bound Dependency Property Rate changes, you should move the old value into an IEnumerable that's defined on the graph control itself (The same place that has the DP) and use that to draw the lines. I personally would create a class named MyControlData and add an instance of that to the control.
You might also want to add a Timer and move the current Rate to the IEnumerable when it Elapses, so longer streaks of the same rate will appear as multiple bars. Depends on how you actually determine progress. You might get into the following dilemma here : The Rate changes at a different interval than the Percentage in most cases - what floats your boat?
Keeping the history in your control's scope leaves your application agnostic to the history of your Rate, but lets your control display it as required.
To use DataBinding in a UserControl, edit the <UserControl x:Name="myControl"> node in Control.xaml and add a name like shown here. Wherever you want to bind, refer to ElementName=myControl. Please note that you will have to implement INotifyPropertyChanged on the Control (or on MyControlData) if you want to achieve this - or, and that would be advisable, directly implement it as a dependency property.
And BTW, if you have no idea how to achieve what you intend to have a look into ItemsControl. I think what you want to do can easily be achieved by means as simple as using ItemsControl and ItemsTemplate, where the ItemsSource is your historical data and the ItemTemplate depicts your current rate in comparison to your MaxRate. MaxRate is another property you can set from the DependencyProperty Rate's changed handler.