UserControl vs SurfaceWindow - wpf

I am trying to use values i declare inside a UserControl class to change things inside the SurfaceWindow class. Now what i know so far is that i have to use a DependencyProperty to get the value from the UserControl and then put it inside a public string.
public string MapValue
{
get { return (string)GetValue(MapValueProperty); }
set { SetValue(MapValueProperty, value); }
}
public static readonly
DependencyProperty MapValueProperty = DependencyProperty.Register("MapValue", typeof(string), typeof(MapManager));
Now my question is, how do i bind the public string (that is inside the UserControl) to a element (inside the SurfaceWindow)?
If i use the DependencyProperty do i make a new class or do i put it in the usercontrol code?
I would be very happy if someone could help me with this problem..

As far as i can tell you are trying to bind to a dependency property of some control in your window.
If this is the case you could use the ElementName syntax in the binding declarations such as:
<TextBlock Text="{Binding ElementName=MapControl, Path=MapValue}"/>

I had already have this inside my window control:
<Image x:Name="iGroundPlan" Source="{Binding ElementName=MapManager,Path=MapValue}" />
(MapManager is the name of my usercontrol)
But looks like it aint working, and i dont know why.. Its like the windows never knows when the value MapValue is updated in my usercontrol =\

Related

Create StaticResource from DataContext?

All,
Is it possible to create a StaticResource from an object in DataContext (without added code-behind)? Take for example a DependencyProperty of a UserControl:
public static DependencyProperty ViewModelProperty = DependencyProperty.Register("ViewModel", typeof(IVMHeaderGeneric), typeof(UIHeader), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
public IVMHeaderGeneric ViewModel
{
get
{
return (IVMHeaderGeneric)this.GetValue(ViewModelProperty);
}
set
{
this.SetValue(ViewModelProperty, value);
}
}
IVMHeaderGeneric is an interface that is instantiated as a class by the consumer of this user control.
What I need to do is, somehow (preferably without code-behind), add this to the UserControl's Resources, thus allowing me to perform data-bindings on UIElements that do not inherit DataContext (i.e. the DataGridColumn comes to mind).
Thanks in advance.
I think that you could not create an instance the interface in the xaml resources, because, as you said, the implementation is out of UserControl scope.
Instead of creating StaticResource, you can use Binding to refer to the UserControl DataContext property. For example, if you give the name of your root element, Root, you can write the following:
<DataGridColumn SomeDependencyProperty="{Binding ElementName=Root, Path=ViewModel.Property}" />

Silverlight: How to add a Dependency Property to multiple controls?

Is it possible to create a Dependency Property for multiple controls without resorting to subclass every one of it?
I thought about using Attached Properties but they nest only one level deep as far as I understand it.
I want something like this to be possible:
<!-- MyDataGrid implements the new Attached Properties SourceData and TargetData -->
<MyDataGrid>
<StackPanel>
<TextBox MyDataGrid.SourceData="{Binding Somewhere}" MyDataGrid.TargetData="{Binding Somewhere}" />
</StackPanel>
<CheckBox MyDataGrid.SourceData="{Binding Somewhere}" MyDataGrid.TargetData="{Binding Somewhere}" />
</MyDataGrid>
This won't work since the Attached Properties wouldn't be found in the TextBox since it's no direct descendent of MyDataGrid.
Background is that I try to automatically convert an old Xaml-like Gui-syntax into real Xaml and with the old system it was possible to set different sources and targets for changed data. Now I'm searching for a Xaml-solution that doesn't involve subclassing every control there is.
Thanks in advance.
are you sure you are using Attached property correctly?
public static readonly DependencyProperty SourceDataProperty = DependencyProperty.RegisterAttached(
"SourceData", typeof (string), typeof (MyDataGrid), new PropertyMetadata("test"));
public static void SetSourceData(DependencyObject obj, string sourceData)
{
obj.SetValue(SourceDataProperty, sourceData);
}
public static string GetSourceData(DependencyObject obj)
{
return (string) obj.GetValue(SourceDataProperty);
}
This worked for me.Though SetSourceData was not get called, but data was there.
To retrive data.
MyDataGrid.GetSourceData(tbox);
Where tbox is the instance of your TextBox.

Why does data binding to DynamicResource not work?

The following code does not work. How do I make it work?
<Image Source="{DynamicResource {Binding VM.ImageKey}}" />
This is an incorrect usage of the DynamicResource MarkupExtension. Correct it would be:
<Image Source="{DynamicResource VM.ImageKey}" />
Assuming you have a resource with a key "VM.ImageKey" defined somewhere like this:
<Bla.Resources>
<BitmapImage x:Key="VM.ImageKey" UriSource="C:\Uri\To\Image.jpg" />
</Bla.Resources>
However if you want to bind against some property form the current DataContext you must not use DynamicResource but Binding:
<Image Source="{Binding VM.ImageKey}" />
Assuming your current DataContext is an instance that has a property called VM wich again has a property called ImageKey wich is a derived type of ImageSource.
This behaviour is by design. Binding works only on dependency properties of dependency objects and MarkupExtension is not dependency object.
It cannot work since the DyamicResource is a MarkupExtension and not a dependency property. Databinding only works with dependendcy properties.
However, there is a semi smooth workaround. Create a DynamicTextBlock class that extends a TextBlock.
The xaml:
<TextBlock x:Class="Rebtel.Win.App.Controls.DynamicTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"/>
The codebehind:
public partial class DynamicTextBlock : TextBlock
{
public static readonly DependencyProperty TextKeyProperty = DependencyProperty.Register(
"TextKey", typeof(string), typeof(DynamicTextBlock), new PropertyMetadata(string.Empty, OnTextKeyChanged));
private static void OnTextKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var me = ((DynamicTextBlock)d);
if (e.NewValue != null)
{
me.TextKey = (string) e.NewValue;
}
}
public string TextKey
{
set { SetResourceReference(TextProperty, value); }
}
public DynamicTextBlock()
{
InitializeComponent();
}
}
Usage:
<local:DynamicTextBlock TextKey="{Binding TextKeyProperty}" />
The TextKeyProperty then returns a key that can be found in the ResourceDictionary. The same approach can be taken for an Image and its Source property.
If you want to specify the resource key dynamically you should specify it using the ResourceKey markup extension - not sure if it supports bindings in the way you want it to however. See here for more details.
I'm assuming that in this case, VM.ImageKey refers to a property on a data source whose value you wish to use as a resource dictionary key. The idea being that your data source can determine which image is used by supplying a resource key. (Most of the other answers on this page are unhelpful, because they have unfortunately missed what you're trying to do, assume that you want to use the literal text "VM.ImageKey" as a resource key, which I'm pretty sure isn't what you're asking for.)
This doesn't seem to be supported, but there's another approach that can enable you to select an image resource through a key determined by databinding: https://stackoverflow.com/a/20566945/497397

How to Databind TextBox to Property in CodeBehind

I am using Expression Blend.
Let's say I got:
Public string FirstName{get;set;}
Edit: thanks for the answers, but I'm afraid people didn't understand my question. I do know how to Bind Data in Code or in XAML.
My question is if there is a way to do all that with the Expression Blend Interface without writing it directly. Only with mouse movements.
You would actually want to put the property on a View Model, and use XAML binding, but that is another story.
As you describe your example, you would first need to implement the "FirstName" property as a Dependency Property and not a simple get/set. Here is a great code-snippet from Shawn Wildermuth to save lots of typing (there is a single typo in the snippet you need to fix - "($type$)args.NewValue;"... NewValue has the wrong case in the snippet).
You can bind in XAML to a simple get/set property, but it is a one-way/one-time binding and will not update with changes.
In code, the binding requires two things to be set.
Set the DataContext of the control (or the page) and
Set a data binding on the control.
For the example you mention you could use code like the following (assumes a TextBox control called myTextBox in the Xaml):
using System.Windows;
using System.Windows.Controls;
namespace BindingCodeTest
{
public partial class BindingCode : UserControl
{
public string FirstName
{
get { return (string)GetValue(FirstNameProperty); }
set { SetValue(FirstNameProperty, value); }
}
// Using a DependencyProperty as the backing store for FirstName.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty FirstNameProperty =
DependencyProperty.Register("FirstName",
typeof(string),
typeof(BindingCode),
new PropertyMetadata(string.Empty,
new PropertyChangedCallback(OnFirstNameChanged)));
static void OnFirstNameChanged(object sender, DependencyPropertyChangedEventArgs args)
{
// Get reference to self
BindingCode source = (BindingCode)sender;
// Add Handling Code
string newValue = (string)args.NewValue;
}
public BindingCode()
{
InitializeComponent();
myTextBox.DataContext = this;
myTextBox.SetBinding(TextBox.TextProperty, new System.Windows.Data.Binding("FirstName"));
FirstName = "First name"; // Sample change
}
}
}
In Blend 4, on the 'Data' tab > New sample Data.. > name data source as you like, f.e. 'MySampleDataSource'. Then your 'MySampleDataSource' will have a '+' button (the same Data tab on the right) with 3 options. Choose 'Add simple property' and name it 'FirstName'. Then drag that property on your TextBox or TextBlock.
The result is like this:
<TextBlock x:Name="firstName" Text="{Binding FirstName}"/>

Problem with Binding Dependency Property on a UserControl

I have a two userControls (IconUserControl & DisplayUserControl), I'm having a problem with binding dependency properties, here's some detail:
IconUserControl has a bool DP of IsDisplayShown
DisplayUserControl has a bool DP of IsDisplayShown
In the XAML I have:
<local:DisplayUserControl
x:Name="DisplayUserControl"
IsDisplayShown="{Binding ElementName=IconUserControl, Path=IsDisplayShown, Converter={StaticResource DummyConverter}}" />
<local:IconUserControl
x:Name="IconUserControl" />
When IconUserControl.IsDisplayShown is set to true, I can see in the DummyConverter this value getting passed, but it never sets DisplayUserControl.IsDisplayShown.
However, if in the codebehind for the View I set DisplayUserControl.IsDisplayShown = true;, then it works fine.
I have the DataContext for both UserControls set to "this" in the constructor. I've tried to fiddle with the "Mode" property of the binding.
*Note: DummyConverter just returns the value, I only have this to confirm that the Binding is trying to work.
What am I doing wrong?
Edit:
Here's the two DPs:
public bool IsDisplayShown
{
get { return (bool)GetValue(IsDisplayShownProperty); }
set { SetValue(IsDisplayShownProperty, value); }
}
public static readonly DependencyProperty IsDisplayShownProperty =
DependencyProperty.Register("IsDisplayShown", typeof(bool), typeof(IconUserControl), new UIPropertyMetadata(false));
public bool IsDisplayShown
{
get { return (bool)GetValue(IsDisplayShownProperty); }
set
{
if (value)
ShowOpenItems();
else
HideOpenItems();
SetValue(IsDisplayShownProperty, value);
}
}
public static readonly DependencyProperty IsDisplayShownProperty=
DependencyProperty.Register("IsDisplayShown", typeof(bool), typeof(DisplayUserControl), new UIPropertyMetadata(false));
This should help you, but probably won't solve the whole problem. It is a good place to start, though. Adding this code will cause debugging info for the binding to dump to your Debug window in Visual Studio.
add this namespace to your xaml....
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
then, your binding, add this:
diagnostics:PresentationTraceSources.TraceLevel=High
check Bea Stollnitz article for more information
That just doesn't make sense =) Should work =)
Did you try to set Mode=TwoWay in the binding?
Are you sure you got the DP definition right? Can you add them to the post?

Resources