Is it unconventional to use a Property this way? [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I am creating a custom button control for a WPF application. The Button contains a ViewBox which in turn contains a TextBlock like this;
<Button>
<Viewbox>
<TextBlock Name="TextHolder"/>
</Viewbox>
</Button>
I want outside classes in C# to be able to access and change the text directly via a Property, like so;
public string Text
{
get { return TextHolder.Text; }
set
{
TextHolder.Text = value;
}
}
I am wondering if this is consider bad practice or not?
Thanks.

This piece of code of yours allows the part of the code that is responsible for "business logic" to look like:
this.Text = "mom";
instead of for example:
this.TextHolder.Text = "mom";
Difference is in accessing/exposing the TextHolder UI component. You don't want to expose them. That should be just a details of the 'presentation style'. Ideally the code should not care how the visuals look like (well, unless you are actually writing the code for the visual component like 'TextBlock'). What if you change your UI and TextHolder is no longer there and now you have a different presentation of the text, and it for example doesn't have control.Text but rather control.Data or control.Content? If TextHolder were exposed, you'd have to correct the code everywhere. With your piece of code, that "everywhere" uses your property this.Text, and TextHolder is hidden, so when it's gone, you just change the Text property getter/setter. This is a great thing.
And that's why, if anyone told you anything negative about this, would be wrong. Everything is better than scatterring accesses to UI component all over your business logic code. If you wanted to address that problem and came up with such a solution - great!
That being said, it's not the best you could have, and this is where the praise ends.
First of all you said you are using WPF. In WPF you there's a mechanism called data bindings. If you never used it, let me just say it's .. powerful. Unwieldy at times, but powerful. If you learned to and used data bindings, you would still have the Text property, but your code would not have TextHolder at all, not even in the getter/setter of .Text
Going further, once you learn at least the basics of data bindings, you can take it further and look at MVVM pattern. This one has the power of annihilating .xaml.cs and moving everything to view-agnostic "view models" - plain C# classes that have Properties and that never touch UI directly. WPF has mechanisms to observe them for any changes in their properties and then automatically refreshing the UI. It works two way - clicking/writing to a control may refresh properties in the "view model".
But there's a cost. It's all fine and dandy, but requires you to write some a bit repetitive boilerplace code and keep some defined patterns (though tools like i.e. PostSharp can do it for you, or frameworks like Caliburn.Micro can greatly simplify data binding expressions in XAML..).

Related

Who uses NotifyCollectionChangedEventArgs' features? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
This is a follow-up to my question, How does WPF handle CollectionChanged events for custom collections?.
According to Alex.Wei's answer (and the source code of IndexedEnumerable) WPF ignores the specifics of the NotifyCollectionChangedEventArgs (e.g. Action) and always reacts the same, ultimately as if Action == Reset.
So my questions: Who uses NotifyCollectionChangedEventArgs' features and, if I raise the event manually (for a custom class) does it make sense to specifiy the details (if they are never evaluated)? Also, why does WPF behave like this - isn't this a potential performance killer?
I am sorry if I didn't make things clear in last anwser. Actually, WPF behaves according to specifics of the NotifyCollectionChangedEventArgs like it means to be, and IndexedEnumerable just a tool that let CollectionView or other componets of WPF access to the source collections that didn't implement IList throngh an index easily. For example, after you bind a collection to ItemsControl.ItemsSource, the things in below will happen.
ItemsControl will specify the collection as the source of its Items property.
Items property which is an ItemCollection will obtain a CollectionView by calling CollectionViewSource.GetDefaultCollectionView method.
The view will try to subscribe CollectionChanged event of the source collection and act accordingly.
ItemCollection will also subscribe CollectionChanged event of the view and act accordingly.
And also, ItemsControl subscribe CollectionChanged event of the Items and act accordingly form the beginning.
So, the answer to you questions is that a lot of WPF classes are using NotifyCollectionChangedEventArgs' features and you definitely need to riase CollectionChanged event correctly by providing all the details whatever you collection was implemented IList or not.
My experience is that WPF is going to raise an exception if you provide wrong indices or multiple elements in an Add or Remove action.
Apart from that, there is a range of frameworks (NMF Expressions, BindableLINQ, ContinuousLinq, Obtics) that make use of these CollectionChanged events in order to implement INotifyCollectionChanged on queries. These frameworks will heavily rely on the details that you put in the event, despite you can of course always resort to a reset event.
Take a look on my ObservableComputations library. That library uses NotifyCollectionChangedEventArgs very widely.

Passing data from a handler to another. very basic issue about OOP

This may be a really basic question to experienced programmers but I started on VB6, and now I'm trying to accomplish same stuff on C# which is object oriented.
Suppose I have a class with a method to add two numbers on textboxes and I run that in the click handler of a button (Doesn't matter if it is static or not), then I have the result and I display it on the screen (maybe in another textbox), the user click another button, how do I recover the result on the other button handler?, what's the best practice?, I know I can read the result on the textbox, but if the result was displayed on a Messagebox.Show or in console?.
What's the best practice to save results instead of using helper textboxes or global variables?
On VB6 I use invisible textboxes, so my forms looks really messy, but thats the way to there.
Using C# + XAML + WPF
Usually that is what a model is for. It is the data-state of what is shown (and more, as some information may not be displayed at all times or just used as utility). The view often has a reference to the model which you then can access in the handlers and manipulate.
I'd suggest reading up on design patterns like Model-View-Controller and for WPF specifially Model-View-ViewModel.
Also, WPF has a few powerful mechanics like data binding, which makes synchronizing your data with the view a lot easier, do not treat your view as a model.

Form updation based on users choice from combobox [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am making an application where the user has to choose a value from a combobox. Based on the users choice the form should be filled with relevant labels and textboxes. How do I achieve this?
One way I think this could be achieved is by creating all labels and textboxes, and based on the users choice hide the irrelevant ones. But this seems to be very cumbersome. Is there any neat way to do it?
Could you just give me leads from where I could pick up the many
ways? #Jumpei – user2276910 8 mins ago
Just you know, everything in the comments was a lead of some kind. Whichever approach you chose, showing/hiding data is essential. Your combobox selection is a private case. Much more frequently, you gonna need/use this to handle user access so there is no way you gonna start building your application and at some point discover that you can't show/hide data or controls. That's just not the case. In fact since each approach will give you that option, to get a concrete answer will require a lot more information about the project itself and the overall architecture than just this one particular form.
Having said that I will suggest you approach which I think is not the best one, but very intuitive and at some point when you feel more confident you change this.
So in order to achieve this create the form setting the default visibility to all elements. Adding/removing controls dynamically is not that trivial but setting the visibility option is pretty straight forward so I think it's better to start by using the visibility option.
When you are ready with the default state of the form you gonna need few methods. First, an event handler for the combobox select which should be something like this:
private void ComboBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
ComboBox comboBox = (ComboBox) sender;
string userSelection = (string)ComboBox1.SelectedItem;
From now on you should make a few things. First check if the userSelection is something valid. This check is essential, after you are sure that this is valid selection you gonna proceed (and we are still in the SelectedIndexChanged event) by calling a a method :
private void SetControlsToDefault()
{
}
This method will contains all your controls with their default visibility status. That's required because when the user make more than one selection with the combobox if we don't hide the once that were shown on the previous selection you will end up with visible controls when they should be hidden for the certain selection.
So once we are sure that the form is returned to it's initial state we need to check what exactly has the user selected and show the relevant controls.
Here some would suggest to use switch I'll suggest if-else if statements since I think this will make it more understandable but you can change it if you like so again in the event handler after calling SetControlsToDefault(); we have this:
if (userSelection.Equals("selection1"))
{
ShowControlsForSelectionOne();
}
else if (userSelection.Equals("selection2"))
{
ShowControlsForSelectionTwo();
}
else if (userSelection.Equals("selection3"))
{
ShowControlsForSelectionThree();
}
where ShowControlsForSelectionOne(), ShowControlsForSelectionTwo(), ShowControlsForSelectionThree() are all private methods where you gonna set the visibility only to those elements relevant to the selection. And that should be all. This is one of the many ways to complete this task.

Making a grid of objects

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.

Best approach to develop WPF application [closed]

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?

Categories

Resources