I have a custom control in Silverlight, the change of property via property window is not getting updated until I build the application once again. What could be the problem?
Say for example. I have a control called Shapes. If I select type of the shape as "Octane" it should show a sample octane in blend design-time surface.
But, in my case it is not happening, the blend designer is not getting updated untill I build the application again. Please advice me on this.
I don't want to put the consumer in trouble by letting them build it for every change in property value they make.
Note: All the exposed properties in the control are dependency property.
Have you implemented the setter of your property so that the controls update when the property's value is changed?
(BTW, just because I'm curious, what's an octane shape? does it have something to do with chemistry?)
What I had was a Properties of type CommonStyles for applying styles. For example,
CommonStyles will contains dp's like Background, Foreground, Thickness, etc.,
The mistake I done was, I directly assigned the values like below. In base class. [ShapeStyle is a dp of type CommonStyle]
//// Both properties are dp's but, assigned them like normal property. This caused the issue
ShapeBase.Background = this.Shape.ShapeStyle.Background;
ShapeBase.Foreground = this.Shape.ShapeStyle.Foreground;
ShapeFace.Background = this.Shape.ShapeFaceStyle.Background;
...
When, I change the background property it won't update my ShapeBase.Background property. Since, it is not dependency bound.
I resolved it by, dp binding. Like below.
this.ShapeBase.SetBinding(BackgroundProperty,
new Binding() {
Source = this.Shape.ShapeStyle,
Path = new PropertyPath("Background") });
Related
I'm developing a WPF/MVVM application and I have a listbox binding to data in a ViewModel. At various points I need the view model to cause the listbox to scroll to a given element.
How can I do this without creating a custom control and while still maintaining good separation of concerns?
I've currently got it working by creating a custom behavior class in the view layer with a dependency property VisibleIndex which the XAML code then binds to an integer in the view model:
<ListBox x:Name="myListBox"
local:ListBoxVisibilityBehavior.VisibleIndex="{Binding VisibleIndex}">
When the integer is set it triggers the dependency properties update handler which tells the listbox to scroll to the associated index.
This seems a bit hacky though because the dependency property value is never changed by the listbox and the update handler only gets called when the value changes, so the only way to ensure that the relevent item is visible is to do something like this:
// view-model code
this.VisibleIndex = -1;
this.VisibleIndex = 10;
The only reason I'm using a behaviour class at the moment is for binding my custom dependency property, is there a way to do something like this with events instead?
Attached properties are somewhat required in your case - as at some point, 'somewhere' you need to call the following method...
ListBox.ScrollIntoView(item)
or
ListBoxItem.BringIntoView();
And for that you need some sort of code behind - and attached properties/behaviors are a nice way of packaging that, w/o impacting your MVVM.
Having said that - if you just need to have your 'selected item' scrolled into view at all times (which is the case most of the time). Then you could use a different attached-property based solution (that again):
mvvm how to make a list view auto scroll to a new Item in a list view
All you have to do then is to set or bind to SelectedItem.
That's a bit 'nicer' if you wish - but the mechanism is the same.
For anyone else interested in the answer to this one of the MS engineers on the WPF forum cleared it up for me. Instead of binding to an event directly you bind to a wrapper object that encapsulates that event. The behaviour can then grab the reference to the wrapper from its DP and do whatever it wants with it i.e. subscribe to the event, trigger it etc.
I'm using a 3rd party control (in this case, Telerik's RadChart control), which has a complex inner ControlTemplate that encompasses several elements of the chart. Unfortunately, not all parts are exposed explicitly for me to style, and I find myself wanting to set a property on a particular sub-element inside the ControlTemplate, either via XAML or via code. After struggling with the XAML for a while, I settled for a code-centric approach, but I'm still stuck.
Using Snoop, I can see that the top-most ChartArea control (which I can access) renders an AxisX2D object named PART_AxisX, which in turn has a template which contains the PART_AxisLabels object, which is the one I need to style. (Incidentally, the property I want to set is AlternationCount, but I couldn't find a less hacky way of getting to it).
I tried to use the ControlTemplate.FindName method (as shown here) to get the AxisX2D object, and then again on that object to get the AxisLabels object, but FindName always returns null:
var chartArea = myChart.DefaultView.ChartArea;
var visualAxisX = chartArea.Template.FindName("PART_AxisX", chartArea) as AxisX2D;
even though Snoop confirms that chartArea is, in fact, the AxisX2D's TemplatedParent. I checked in the debugger and I could find PART_AxisX in chartArea's internal Template property.
So my questions are:
1) What am I doing wrong here?
2) Is there a better way to approach this that isn't as roundabout as this?
The solution is to wait till after the Loaded event has occurred on the Control.
When this event has occurred you know that the Template has been applied and the visual tree has been built for the control, and so you can then access the elements using FindName.
http://blogs.msdn.com/b/mikehillberg/archive/2006/09/19/loadedvsinitialized.aspx
Slightly related link given here for case when using a Content Template on a ContentControl.
Why would 'this.ContentTemplate.FindName' throw an InvalidOperationException on its own template?
I have a Window that uses DataTemplates to display a different UserControl (view) in a ContentPresenter based on the type of its Content property, which is bound to a property that holds the current viewmodel. In this way, by changing the viewmodel property with an event, I can facilitate the basic back/forward navigation I need.
When creating a new viewmodel, it is passed a reference to the current one. Going back to the old viewmodel instance works fine for a CheckBox control, but not for a UserControl I made that contains a TextBlock and a ComboBox.
The problem is that, when the view containing the ComboBox gets unloaded, the ComboBox's ItemsSource gets nulled, which triggers it to clear its SelectedItem/Text properties, which are for some reason still bound to my viewmodel--thus clearing the data it stores. I don't know how to manually unbind them at the appropriate time. (Again, the CheckBox works just fine.)
I have read that other users have had this exact same problem. For them, changing the declaration order of the ItemsSource and SelectedItem/Text bindings so that the attributes for the latter are placed before the former fixes the issue. However, in my case, it does not. Others have also fixed the issue by ignoring null/empty values, but this won't work in my case.
I could work around the issue by copying the interesting data to a separate object, and reloading it from that, but I would need to add code to trigger reloading the data = more data linkage code to maintain.
I could also avoid using DataTemplates and manually add the UserControls in the codebehind, which would allow me to break the data binding before removing the UserControl. But this runs counter to the point of MVVM.
I'm not above modifying my very non-MVVM UserControl to handle any events on the ComboBox it contains to work around this issue.
UPDATE:
I have narrowed down the issue a little bit. I refactored the code so that it manually creates and adds the view UserControl based on which viewmodel has been set. The issue now only occurs when I set the DataContext of the view UserControl to null. If I simply replace the view without removing the reference, it no longer erases the values in question. Is this a usable workaround, or does it create issues like memory leaks?
Maybe something that would "open mind" for a simpler solution... If I understand your problem, it's similar to a past problem we had. In our case, we simply made the assumption that it's not possible to set a specific value to null when accessed by the bound property, so we tweaked the appropriate ViewModel Properties a bit:
public MyItem SelectedItem {
get {
return Model.MyItem;
}
set {
if (value != null) {
// Set and notify if not null
Model.MyItem = value;
OnPropertyChanged("SelectedItem");
}
else // just notify when trying to set to null
OnPropertyChanged("SelectedItem");
}
}
Using such tweaked properties we were able to block any try to set the value to null, by calling OnPropertyChanged(..) insead, the existing value was recalled by the UI. If there is a need to be able to set a value to null, you have to provide a seperate property allowing that.
Not sure if this applies to your problem.
Good luck.
UPDATE
oh, I see probably this describes same method as "Others have also fixed the issue by ignoring null/empty values" which seems not to work in your case. But I dont unterstand why it shouldn't.
This is a known bug in the early versions of WPF caused by event leapfrogging. It was fixed for the Selector-derived controls in .NET 4.0.
See this blog post for more details: http://blogs.interknowlogy.com/2011/03/09/event-leapfrogging/
I have worked around the issue by adding a property Active and corresponding Activate()/Deactivate() methods to my base viewmodel class, and calling these as appropriate when swapping out viewmodels. This fits into my application pretty well. I'm still open to other suggestions, of course.
somehow I am going in circles here. Please forgive me if the answer to this question is obvious.
I want to react to changed properties in the ViewModel in the View. When the properties (bool) change the View should start an animation (BeginStoryBoard).
Actually in my application there are 4 of these properties each with its own name in the VM and two desired animations each (hide/show) for the respective 4 container view elements.
When setting these Triggers (tried DataTrigger/Trigger/EventTrigger) directly in the respective container elements (all of them of custom type SizerControl derived from ContentConrol) wpf gave me errors suggesting using a style. When setting a style directly in the container elements I got: "The tag 'Style.Triggers' does not exist in XML namespace ..."
But when using a style in a global ResourceDictionary I am at a loss how to bind to the 4 containersto get the "input" value for the trigger.
Do you have a suggestion how to solve this from an architecture pov? Maybe I am already down too far the wrong path to see the obvious solution.
Thanks a bunch,
Hinnerk
You can do this with a DataTrigger and a StoryBoard.
MSDN has a full sample describing the process, with code, documented in How to: Trigger an Animation When Data Changes.
I am attempting to create a sukodu (like crossword) player in WPF, and I realize that I have a whole bunch of controls that will need to know the sudoku grid to function.
Because of this, I think the Sudoku Grid object would be a good candidate to create a dependency property. I am about to start the work, but I have some lingering questions:
Who should own the SudokuGrid dependency property? I am thinking the main window UI element should.
Should I set it as a shared dependency property, where all user controls that represent a part of a sudoku grid simply add themselves to the property via .AddOwner() method?
OR
Set it up as an attached property, defined at the main window, and allow child user controls to set up accordingly?
I don't really want child controls to be allowed to set their own grid property value though, so at this time I am leaning towards shared dependency property, but I am not sure it does what I think it does.
Ultimately what I want is one property where if it's set on a parent UI element, all children UI elements that knows about the property will share the same value, overriding any prior value / setting. Does shared dependency do that?
I know it's a bit long winded, but any help would be much appreciated!
I think what you want is an attached property with the Inherits FrameworkPropertyOption. That we every control that wants to know about the grid can just find the grid by getting the value of the attached property (assuming it is set higher up in the tree). This article goes over attached properties and how to set them up.
Alternativly you might like to try out the Model View View-Model (MVVM) pattern and implement the Sudoku grid as a view-model class which each cell being a ceperate view-model class. That way the whole sudoku puzzel is completly seperate from the UI and the UI can just bind to it using appropriate data templates.
For more info on the MVVM pattern se the following:
http://www.codeproject.com/KB/WPF/MVCtoUnitTestinWPF.aspx
http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx