WPF Static Resource - wpf

I'm trying to bind a string in the Window resources to a property.
I know that that binding works on dependency properties.
Does the string class in WPF have a dependency property?
Thank you
<Window.Resources>
<sys:String x:Key="strWindow"> Content= myProperty </sys:String>
</Window.Resources>

If you are exploring, then all I can say is that no one does it this way.
As for your question, string class does not dependency property of any kind. Only subclasses of DependencyObject class can have DependencyProperty. All WPF controls are subclasses of DependencyObject, and most of the properties we commonly access are coded as dependency property.
For example, TextBox is a subclass of DependencyObject, and has a Text property coded as a dependency property.
Do note that you can also build your own custom controls (by subclassing from FrameworkElement or one of its subclass), and write your own properties. If you don't code the property as a dependency property, that property will not be bindable.

Related

MVVM + UserControl + Dependency Property

Alright, this is somewhat related to this question: WPF Printing multiple pages from a single View Model
I tried to follow the advice given there but now I am stuck.
My application uses a MainView.xaml and the appropriate MainViewViewModel.cs, I am using MVVM Light in the background.
Now - according to the post - it seems I have to do the following:
Create a user control
Expose some properties from the user control
Make sure the view model shows these properties
The idea is clear but I am stuck when trying to notify each other.
My user control (UcTest.xaml) exposes a Dependency Property:
public string SpecialText
{
get { return (string)GetValue(SpecialTextProperty); }
set
{
SetValue(SpecialTextProperty, value);
}
}
// Using a DependencyProperty as the backing store for SpecialText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SpecialTextProperty =
DependencyProperty.Register("SpecialText", typeof(string), typeof(UcTest), new PropertyMetadata(new PropertyChangedCallback(SpecialTextChangedPropertyCallback)));
private static void SpecialTextChangedPropertyCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// Do something
Debug.WriteLine("Ffgdgf");
}
Alright, so I do now have a user control which has some dependency properties. Yet, these properties are completely separated from my ViewModel properties (those are the ones which shall be displayed).
So basically I have two possibilities:
How can I now tell my ViewModel for the UserControl that some properties have changed?
Is there a possibility to forget about the dependency properties and access the view model directly?
Additional info #1:
I have uploaded a (simple) example of what I am trying to do here: Example Project. I would like to change the value of the label in UserControl1 (via the binding property in the ViewModel for UserControl1) from my MainViewViewModel.
You would usually bind the UserControl's property to the ViewModel property. A two-way binding would work in both directions, from ViewModel to View and vice versa.
<Window x:Class="TestApplication.MainWindow" ...>
<Window.DataContext>
<local:MyViewModel/>
</Window.DataContext>
<Grid>
<local:UcTest SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/>
</Grid>
</Window>
To directly access the ViewModel object in the above example, you could simply cast the UserControl's DataContext property to the ViewModel type. The DataContext is inherited from the MainWindow.
var viewModel = DataContext as MyViewModel;
var property = viewModel.MyViewModelProperty;
You could of course also directly assign a specialized ViewModel instance to the UserControl's DataContext:
<local:UcTest SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/>
<local:UcTest.DataContext>
<local:UserControlViewModel/>
</local:UcTest.DataContext>
</local:UcTest>
or you may create the ViewModel instance as a resource in a resource dictionary and assign the DataContext like this
<local:UcTest DataContext="{StaticResource MyUserControlViewModel}"
SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/>
Alright, after hours of googling it appears that the "correct" approach to this is not to do it at all. The general approach is to keep the data in your MainViewModel and not use an additional ViewModel for the UserControl (which I find a little ... well .. not so good). The main problem is that there is no easy mechanism to get the Data from the Dependency Property to the ViewModel.
For printing, I have now gone back to doing it purely in code.

DataBinding in custom class

I wanna make a databinding in a custom class.
But it seems different from normal databinding.
For example, I have a custom class DisplayInfo with a properties DisplayText(string), DisplayStyle(string) and DisplayDescription(string).
and in another custom class ViewUI that contains a property DisplayData which is of type DisplayInfo.
for example:
public class ViewUI
{
....
public DisplayInfo DisplayData { get; set; }
....
}
I want to do DataBinding of the DisplayText in the Xaml. How could I do so?
reference:
<Page ......>
.....
.....
.....
<ViewUI .......>
<ViewUI.DisplayData>
<DisplayInfo Description="Description 123456...." DisplayStyle="Style123" DisplayText = "{Binding.....}"/> <!-- (How to do databinding here or in other place?) -->
</ViewUI.DisplayData>
</ViewUI>
</Page>
You have to change properties in custom class to dependency properties. If property of your class is dependency property then you are able to bind it in xaml.
For more info about dependency property visit http://msdn.microsoft.com/en-us/library/ms753358.aspx
What Is a Dependency Property?
You can enable what would otherwise be a common language runtime
(CLR) property to support styling, data binding, inheritance,
animations, and default values by implementing it as a dependency
property. Dependency properties are properties that are registered
with the WPF property system by calling the Register method (or
RegisterReadOnly), and that are backed by a DependencyProperty
identifier field. Dependency properties can be used only by
DependencyObject types, but DependencyObject is quite high in the WPF
class hierarchy, so the majority of classes available in WPF can
support dependency properties. For more information about dependency
properties and some of the terminology and conventions used for
describing them in this SDK, see Dependency Properties Overview.

How can I bind from a user control to an external object in XAML?

I have an image inside a user control that I want to bind it's visibility to a property I have set up in a class object. The dependency properties are set up and working correctly, but I don't know how to set the binding properly on the image.
The user control and class object are in the same namespace. I thought I would need to set the ElementName to the window or the RelativeSource to the class object, but I'm not getting it to work out.
Here's what a dependency property looks like (defined in MigrateUserWizardObject.cs, this inherits from DependencyObject, this resides in the UserAccountMigrator namespace):
public static readonly DependencyProperty DatabaseStepCompletedVisibilityProperty = DependencyProperty.Register("DatabaseStepCompletedVisibility", typeof(Visibility), typeof(MigrateUserWizardObject));
public Visibility DatabaseStepCompletedVisibility
{
get
{
return (Visibility)GetValue(DatabaseStepCompletedVisibilityProperty);
}
set
{
SetValue(DatabaseStepCompletedVisibilityProperty, value);
}
}
Here's an image that I want bound to this dependency property (defined in ProgressUserControl.xaml, this inherits from UserControl, this resides in the UserAccountMigrator namespace as well):
<Image x:Name="DatabaseCompleted" Source="{StaticResource GreenCheckMarkSource}" Visibility="{Binding Path=DatabaseStepCompletedVisibility, UpdateSourceTrigger=PropertyChanged}" Height="20" HorizontalAlignment="Right"></Image>
This is due to the fact that the DataContext of the image is the user control. How can I make this work?
I think you should look into using the Model-View-ViewModel pattern. Instead of setting the DataContext to the UserControl, set it to an instance of another class (ProgressViewModel, for example). This view model would have all the properties you want to bind to (including your DatabaseStepCompletedVisibility property) and makes it much easier. Right now you are wanting to bind some things to the UserControl, some things to another object somewhere else, etc.. and, as you have found, makes it difficult. Here is more information:
http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/432/MVVM-for-Tarded-Folks-Like-Me-or-MVVM-and-What-it-Means-to-Me.aspx
Without going that approach, you have to have an instance MigrateUserWizardObject to bind to. You can put that instance in your UserControl (if you insist on using it as the DataContext), then you can bind the the property of the MigrateUserWizardObject property of the UserControl. Also, your MigrateUserWizardObject doesn't have to be a dependency object or dependency property to bind to. A better pattern would be to make it a plain c# class that implements the INotifyPropertyChanged interface.

Expose an inner depedency property to the main user control

I am working in silverlight.
Made a new UserControl called TextBoxWithButton.
Now i want add a new property to my new control called TextBoxBackground.
I did this :
public partial class TextBoxWithButton : UserControl
{
public Brush TextBoxBackground
{
get{return textBox.Background;}
set{textBox.Background = value;}
}
}
This works fine, but when I try to animate this property I get an exception.
I think it's because TextBoxWithButton should be defined as a dependency property but I don't know exactly how to to this.
You need to turn this into a Dependency Property. For details on implementing a DP, see Custom Dependency Properties.
Once you have this setup as a Dependency Property, just bind your (inner) TextBox.Background to the "local" TextBoxBackground property (in xaml). You can then animate the UserControl's TextBoxBackground property as needed, and the "inner" property will change as well.

WPF User Control hell with MVVM and Dependency Properties

This is what I'm trying to do:
I'm writing a UserControl that I want to be consumed by other developers.
I want end users to be able to use my control using Dependency Properties.
<lib:ControlView ControlsText={Binding Path=UsersOwnViewModelText} />
I'm using the MVVM pattern.
I'm binding my ViewModels to their View's using <DataTemplates>
<DataTemplate DataType="{x:Type local:ControlViewModel}">
<local:ControlView />
</DataTemplate>
So I have two questions:
Am I right in thinking that if a UserControl is being consumed in XAML then the UserControl must set the ViewModel as its DataContext when the control's Loaded event fires instead of using the <DataTemplate> method?
How do I allow users to data bind to my control's dependency properties while still being data bound to my ViewModel?
You should separate the two use cases:
The (user) control that will be consumed by other developers.
The user control that will be consumed by your application.
Importantly, the latter depends on the former - not vice versa.
Use case 1 would use dependency properties, template bindings, all the things that go into making a regular WPF control:
MyControl.cs:
public class MyControl : Control
{
// dependency properties and other logic
}
Generic.xaml:
<ControlTemplate Type="local:MyControl">
<!-- define the default look in here, using template bindings to bind to your d-props -->
</ControlTemplate>
You would then define use case 2 as:
MyViewModel.cs:
public class MyViewModel : ViewModel
{
// properties and business logic
}
MyView.xaml:
<UserControl ...>
<local:MyControl SomeProperty="{Binding SomePropertyOnViewModel}" .../>
</UserControl>
Best of both worlds with a clean separation. Other developers depend only on the control, which could (and probably should) be in a completely different assembly than your view model and view.
First off, I don't think MVVM is a good choice if you are developing a UserControl that will be consumed by others. A lookless control is what you really should be developing. Jeremiah Morrill has a blog post about this subject.
With that said, you can set the datacontext with XAML if you have a default public constructor.
Inside ControlView.xaml put:
<UserControl.DataContext>
<local:ControlViewModel />
</UserControl.DataContext>
Basically, instead of binding your UserControl's datacontext to the userControlViewModel, it's better to do it on the first child element of the user control. That way, all the references that you make within the control will be bound to the userControlViewModel, but the dependencies properties can be set from the data context set where you want to use your UserControl.
This is from a project I'm working at:
<UserControl x:Class="Six_Barca_Main_Interface.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Six_Barca_Main_Interface"
xmlns:System="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="900" d:DesignWidth="900">
<DockPanel x:Name="rootDock" >
<TextBlock>{Binding SomethingInMyUserControlViewModel}</TabControl>
</DockPanel>
</UserControl>
Then on the code behind:
public partial class MyUserControl : UserControl
{
UserControlViewModel _vm;
public MyUserControl()
{
InitializeComponent();
//internal viewModel set to the first child of MyUserControl
rootDock.DataContext = new UserControlViewModel();
_vm = (UserControlViewModel)rootDock.DataContext;
//sets control to be able to use the viewmodel elements
}
#region Dependency properties
public string textSetFromApplication
{
get{return (string)GetValue(textSetFromApplicationProperty);}
set{SetValue(textSetFromApplicationProperty, value);}
}
public static readonly DependencyProperty textSetFromApplicationProperty = DependencyProperty.Register("textSetFromApplication", typeof(string), typeof(MyUserControl), new PropertyMetadata(null, OnDependencyPropertyChanged));
private static void OnDependencyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MyUserControl)d)._vm.SomethingInMyUserControlViewModel =
e.NewValue as string;
}
#endregion
Then when you use this on your main view, you can set the dependency property with the value you want to pass to MyUSerControl
A UserControl is part of the "View" in "MVVM" just like the TextBox or ListView controls are part of the View.
Whether you decide to use MVVM to develop your UserControl itself or write it in QBASIC (not recommended) it does not break the MVVM pattern for the consumers of your UserControl so long as they can do every thing they need with your UserControl by binding to DependencyProperty's exposed on your UserControl. i.e. Your UserControl should expose the properties it is dependent upon (hence the name). Once you grasp this DependencyProperty's suddenly make a whole lot of sense and you want their helpful on changed event handlers and default values you specify in their constructor.
If your UserControl is in a different assembly or not I cannot see how that makes a difference.
That said many would advocate you build your UserControl using the MVVM pattern itself for all the good reasons MVVM brings e.g. helping another developer looking at your code. However some things simply are not possible and/or much harder more complex and less performant hacking the XAML to do this - I am not talking about your garden variety Add User Form but for example a UserControl handling the layout of thousands of visuals. Furthermore since you are working in your View you do NOT want your UserControl's ViewModels mixed in with you applications!
Basically I am saying it is well within MVVM not to use MVVM on your View!

Resources