How do i create a usercontrol that i can place stuff into? - wpf

I'm trying to make a custom ScrollViewer uc and it occurred to me that I wouldn't know how to put things within the tags of it. For an example
<CustomScrollViewer>
<This is the place where i want to put things>
</CustomScrollViewer>
Is it possible to define an area where the "inside" things will be put?

You may doing this like as: create a dependency property for UserControl of IEnumerable type, and bind the ItemsSource, that you want scrolling.
MainWindow
<Window x:Class="ScrollViewerUserControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:this="clr-namespace:ScrollViewerUserControl"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<x:Array x:Key="ParametersArray" Type="{x:Type sys:String}">
<sys:String>0</sys:String>
<sys:String>1</sys:String>
<sys:String>2</sys:String>
<sys:String>3</sys:String>
</x:Array>
</Window.Resources>
<Grid>
<this:CustomScrollViewer Width="100"
Height="30"
ItemsSource="{StaticResource ParametersArray}" />
</Grid>
</Window>
CustomScrollViewer.xaml
<Grid>
<ScrollViewer Background="Aquamarine"
Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"
Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}">
<ItemsControl ItemsSource="{Binding Path=ItemsSource, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
</ScrollViewer>
</Grid>
CustomScrollViewer.xaml.cs
public partial class CustomScrollViewer : UserControl
{
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CustomScrollViewer));
public IEnumerable ItemsSource
{
get
{
return this.GetValue(ItemsSourceProperty) as string;
}
set
{
this.SetValue(ItemsSourceProperty, value);
}
}
public CustomScrollViewer()
{
InitializeComponent();
}
}
But I think, in this case it's better create a CustomScrollViewer like this:
public class CustomScrollViewer : ScrollViewer
{
// Your additional logic here
}
And in XAML use like this:
<this:CustomScrollViewer Width="100" Height="20">
<ItemsControl ItemsSource="{StaticResource ParametersArray}" />
</this:CustomScrollViewer>

What do you mean 'put things into'?
In your example of a custom ScrollViewer, it would work exactly how you'd use a normal ScrollViewer, for example:
<ScrollViewer>
<DataGrid /> // or whatever controls you want to place within the scrollviewer
</ScrollViewer>
becomes
<CustomScrollViewer>
<DataGrid /> // or whatever controls you want to place within the scrollviewer
</CustomScrollViewer>
For this kind of layout control, it wraps other controls ... so just extend the ScrollViewer to add whatever changes you want to it.
If you mean having new properties on that CustomScrollViewer then follow Anatoliy's guidelines on creating new dependecy properties, which would allow you to do things like ...
<CustomScrollViewer myCustomProperty="WickeyWickeyWhack">
<DataGrid /> // or whatever controls you want to place within the scrollviewer
</CustomScrollViewer>

Related

How to properly bind a shared property of a sub-usercontrol dependency property

I've 4 different collections. Currently I display thoses 4 collections, but I can only have one element selected at the time.
The view where I display the 4 collection:
<UserControl x:Class="xxx.yyy.vvv.Menu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:xxx.yyy.vvv.Menu"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="450">
<Grid Name="RootContainer">
<Grid.DataContext>
<local:MenuViewModel/>
</Grid.DataContext>
<ItemsControl ItemsSource="{Binding Collection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:CollectionControl Collection="{Binding}" SelectedElement="{Binding Path=DataContext.GlobalSelectedElement,ElementName=RootContainer, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</UserControl>
This is bound to a ViewModel:
public class MenuViewModel : SomeBaseViewModelThatHandleTheNotify
{
public IMyElement GlobalSelectedElement
{
get => GetValue<IMyElement>();
set => SetValue(value); //I NEVER COME HERE!!!)
}
public SomeCollectionContainer Collection
{
get => GetValue<SomeCollectionContainer>();
set => SetValue(value);
}
}
My sub control, has a dependency property, which is changed when the internal ViewModel of the UserControl is changed.
public IMyElement SelectedElement
{
get { return (IMyElement)GetValue(SelectedElementProperty); }
set { SetValue(SelectedElementProperty, value);/*HERE I COME!*/ }
}
public static readonly DependencyProperty SelectedElementProperty =
DependencyProperty.Register("SelectedElement", typeof(IMyElement), typeof(CollectionControl), new PropertyMetadata(null, OnSelectedElementChanged));
private static void OnSelectedElementChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
//Retrieve the sub control ViewModel and set the property
SubControlViewModel subControlViewModel = (SubControlViewModel)((CollectionControl)dependencyObject).RootContainer.DataContext;
subControlViewModel.SelectedElement = (IMyElement)dependencyPropertyChangedEventArgs.NewValue;
}
//In the constructor, I register to PropertyChanged of the ViewModel, and I set the SelectedElement when it change.
So, basically, I come in the SetValue of the dependency property of the UserControl, but I never come in the GlobalSelectedElement property of my main ViewModel.
What did I miss?
EDIT
I tried to directly use two-way binding between my ViewModel and the Dependency Property, doesn't work either:
In my sub control:
<UserControl x:Class="xxx.yyy.vvv.CollectionControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:xxx.yyy.vvv.Menu"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Name="RootContainer" Orientation="Vertical">
<StackPanel.DataContext>
<local:CollectionControlViewModel/>
</StackPanel.DataContext>
<Label Content="{Binding Collection.Name}" Margin="5,0,0,0" />
<ListBox ItemsSource="{Binding Collection.Items}" HorizontalContentAlignment="Stretch" Padding="0" BorderThickness="0" SelectedItem="{Binding SelectedElement, RelativeSource={RelativeSource AncestorType={x:Type local:CollectionControl}}, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</StackPanel>
</UserControl>
I feel that my UserControl DependencyProperty is bound from 2 sides
I've tried to make a small diagram to show my classes.
So my CollectionControl.SelectedElement are correctly set, but the MenuViewModel.SelectedItem are not.
Try to bind to the DataContext of the parent ItemsControl using a RelativeSource:
<local:CollectionControl Collection="{Binding}"
SelectedElement="{Binding Path=DataContext.GlobalSelectedElement, RelativeSource={RelativeSource AncestorType=ItemsControl}, Mode=TwoWay}"/>
Obviously using an ElementName doesn't work. This is because of namescopes. The CollectionControl element in the ItemTemplate is not in the same namescope as "RootContainer".

How to correctly bind to a dependency property of a usercontrol in a MVVM framework

I have been unable to find a clean, simple, example of how to correctly implement a usercontrol with WPF that has a DependencyProperty within the MVVM framework. My code below fails whenever I assign the usercontrol a DataContext.
I am trying to:
Set the DependencyProperty from the calling ItemsControl , and
Make the value of that DependencyProperty available to the ViewModel of the called usercontrol.
I still have a lot to learn and sincerely appreciate any help.
This is the ItemsControl in the topmost usercontrol that is making the call to the InkStringView usercontrol with the DependencyProperty TextInControl (example from another question).
<ItemsControl ItemsSource="{Binding Strings}" x:Name="self" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<Style TargetType="v:InkStringView">
<Setter Property="FontSize" Value="25"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</DataTemplate.Resources>
<v:InkStringView TextInControl="{Binding text, ElementName=self}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here is the InkStringView usercontrol with the DependencyProperty.
XAML:
<UserControl x:Class="Nova5.UI.Views.Ink.InkStringView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
x:Name="mainInkStringView"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding TextInControl, ElementName=mainInkStringView}" />
<TextBlock Grid.Row="1" Text="I am row 1" />
</Grid>
</UserControl>
Code-Behind file:
namespace Nova5.UI.Views.Ink
{
public partial class InkStringView : UserControl
{
public InkStringView()
{
InitializeComponent();
this.DataContext = new InkStringViewModel(); <--THIS PREVENTS CORRECT BINDING, WHAT
} --ELSE TO DO?????
public String TextInControl
{
get { return (String)GetValue(TextInControlProperty); }
set { SetValue(TextInControlProperty, value); }
}
public static readonly DependencyProperty TextInControlProperty =
DependencyProperty.Register("TextInControl", typeof(String), typeof(InkStringView));
}
}
That is one of the many reasons you should never set the DataContext directly from the UserControl itself.
When you do so, you can no longer use any other DataContext with it because the UserControl's DataContext is hardcoded to an instance that only the UserControl has access to, which kind of defeats one of WPF's biggest advantages of having separate UI and data layers.
There are two main ways of using UserControls in WPF
A standalone UserControl that can be used anywhere without a specific DataContext being required.
This type of UserControl normally exposes DependencyProperties for any values it needs, and would be used like this:
<v:InkStringView TextInControl="{Binding SomeValue}" />
Typical examples I can think of would be anything generic such as a Calendar control or Popup control.
A UserControl that is meant to be used with a specific Model or ViewModel only.
These UserControls are far more common for me, and is probably what you are looking for in your case. An example of how I would use such a UserControl would be this:
<v:InkStringView DataContext="{Binding MyInkStringViewModelProperty}" />
Or more frequently, it would be used with an implicit DataTemplate. An implicit DataTemplate is a DataTemplate with a DataType and no Key, and WPF will automatically use this template anytime it wants to render an object of the specified type.
<Window.Resources>
<DataTemplate DataType="{x:Type m:InkStringViewModel}">
<v:InkStringView />
</DataTemplate>
<Window.Resources>
<!-- Binding to a single ViewModel -->
<ContentPresenter Content="{Binding MyInkStringViewModelProperty}" />
<!-- Binding to a collection of ViewModels -->
<ItemsControl ItemsSource="{Binding MyCollectionOfInkStringViewModels}" />
No ContentPresenter.ItemTemplate or ItemsControl.ItemTemplate is needed when using this method.
Don't mix these two methods up, it doesn't go well :)
But anyways, to explain your specific problem in a bit more detail
When you create your UserControl like this
<v:InkStringView TextInControl="{Binding text}" />
you are basically saying
var vw = new InkStringView()
vw.TextInControl = vw.DataContext.text;
vw.DataContext is not specified anywhere in the XAML, so it gets inherited from the parent item, which results in
vw.DataContext = Strings[x];
so your binding that sets TextInControl = vw.DataContext.text is valid and resolves just fine at runtime.
However when you run this in your UserControl constructor
this.DataContext = new InkStringViewModel();
the DataContext is set to a value, so no longer gets automatically inherited from the parent.
So now the code that gets run looks like this:
var vw = new InkStringView()
vw.DataContext = new InkStringViewModel();
vw.TextInControl = vw.DataContext.text;
and naturally, InkStringViewModel does not have a property called text, so the binding fails at runtime.
You're almost there. The problem is that you're creating a ViewModel for your UserControl. This is a smell.
UserControls should look and behave just like any other control, as viewed from the outside. You correctly have exposed properties on the control, and are binding inner controls to these properties. That's all correct.
Where you fail is trying to create a ViewModel for everything. So ditch that stupid InkStringViewModel and let whoever is using the control to bind their view model to it.
If you are tempted to ask "what about the logic in the view model? If I get rid of it I'll have to put code in the codebehind!" I answer, "is it business logic? That shouldn't be embedded in your UserControl anyhow. And MVVM != no codebehind. Use codebehind for your UI logic. It's where it belongs."
Seems like you are mixing the model of the parent view with the model of the UC.
Here is a sample that matches your code:
The MainViewModel:
using System.Collections.Generic;
namespace UCItemsControl
{
public class MyString
{
public string text { get; set; }
}
public class MainViewModel
{
public ObservableCollection<MyString> Strings { get; set; }
public MainViewModel()
{
Strings = new ObservableCollection<MyString>
{
new MyString{ text = "First" },
new MyString{ text = "Second" },
new MyString{ text = "Third" }
};
}
}
}
The MainWindow that uses it:
<Window x:Class="UCItemsControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="clr-namespace:UCItemsControl"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<v:MainViewModel></v:MainViewModel>
</Window.DataContext>
<Grid>
<ItemsControl
ItemsSource="{Binding Strings}" x:Name="self" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<Style TargetType="v:InkStringView">
<Setter Property="FontSize" Value="25"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</DataTemplate.Resources>
<v:InkStringView TextInControl="{Binding text}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
Your UC (no set of DataContext):
public partial class InkStringView : UserControl
{
public InkStringView()
{
InitializeComponent();
}
public String TextInControl
{
get { return (String)GetValue(TextInControlProperty); }
set { SetValue(TextInControlProperty, value); }
}
public static readonly DependencyProperty TextInControlProperty =
DependencyProperty.Register("TextInControl", typeof(String), typeof(InkStringView));
}
(Your XAML is OK)
With that I can obtain what I guess is the expected result, a list of values:
First
I am row 1
Second
I am row 1
Third
I am row 1
You need to do 2 things here (I'm assuming Strings is an ObservableCollection<string>).
1) Remove this.DataContext = new InkStringViewModel(); from the InkStringView constructor. The DataContext will be one element of the Strings ObservableCollection.
2) Change
<v:InkStringView TextInControl="{Binding text, ElementName=self}" />
to
<v:InkStringView TextInControl="{Binding }" />
The xaml you have is looking for a "Text" property on the ItemsControl to bind the value TextInControl to. The xaml I put using the DataContext (which happens to be a string) to bind TextInControl to. If Strings is actually an ObservableCollection with a string Property of SomeProperty that you want to bind to then change it to this instead.
<v:InkStringView TextInControl="{Binding SomeProperty}" />

How to bind a control's property to a property of the control's element?

I need a digit control to my windows phone app.
I try to create a custom control but I can't bind a property of the control to the control's element.
I had added a dependency property to the control
public static readonly DependencyProperty LineThicknessProperty =
DependencyProperty.Register("LineThickness", typeof (double), typeof (DigitControl), new PropertyMetadata(default(double)));
[DefaultValue(10D)]
public double LineThickness
{
get { return (double) GetValue(LineThicknessProperty); }
set { SetValue(LineThicknessProperty, value); }
}
And have tried to bind it to the control's element
<UserControl x:Class="Library.DigitControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid x:Name="LayoutRoot">
<Rectangle Margin="0" StrokeThickness="0" Width="{Binding LineThickness, RelativeSource={RelativeSource Self}}" Fill="#FFFF5454" RadiusX="5" RadiusY="5"/>
</Grid>
</UserControl>
But it doesn't work. Is where a way to bind that property to the element's property?
Do it in the code behind.
Set a name:
<Rectangle x:Name="theRect" Margin="0" StrokeThickness="0" Fill="#FFFF5454" RadiusX="5" RadiusY="5"/>
Then in code behind:
theRect.SetBinding(Rectangle.WidthProperty, new Binding("LineThickness"){Source = this});
Not at PC with Visual Studio, so applogies if it's not 100% compileable! But gives you the general idea.
What you have done wont work because RelativeSource={RelativeSource Self} sets the source to the target object, which is the Rectangle in your case.
And since rectangle doesn't have a LineThickness property, the binding fails.
To get the right binding you can do several things.
The preferable approach would probably be to set this.DataContext = this; in your UserControl contructor, and then simply set the binding as Width="{Binding LineThickness}" in your XAML.
Or you could target the closest element of type UserControl and find the property on that one, if you don't feel like setting the Datacontext:
Width="{Binding LineThickness, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}"
Update
You can also simply give the UserControl a name, and reference it with the ElementName property in the binding:
<UserControl x:Name="uc1" ... </UserControl>
Width="{Binding LineThickness, ElementName=uc1}"

WPF -- Anyone know why I can't get this binding to reference?

<StackPanel x:Name="stkWaitingPatients" Width="300" Margin="0,0,0,-3"
DataContext="{Binding Mode=OneWay, Source={StaticResource local:oPatients}}">
I'm getting StaticResource reference 'local:oPatients' was not found.
Here is the codebehind:
public partial class MainWindow : Window
{
ListBox _activeListBox;
clsPatients oPatients;
public MainWindow()
{
oPatients = new clsPatients(true);
...
To be able to address the object as a StaticResource, it needs to be in a resource dictionary. However, since you're creating the object in MainWindow's constructor, you can set the DataContext in the code-behind like so.
oPatients = new clsPatients(true);
stkWaitingPatients.DataContext = oPatients;
And then change the Binding to this:
{Binding Mode=OneWay}
This is an ok practice if you're not going to be changing the DataContext again, otherwise you'd want a more flexible solution.
Edit: You mentioned ObjectDataProvider in your comment. Here's how you'd do that. First, add an xmlns:sys to the Window for the System namespace (I'm assuming you already have one for xmlns:local):
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Then you can add an ObjectDataProvider to your resource dictionary like this:
<Window.Resources>
<ObjectDataProvider
x:Key="bindingPatients"
ObjectType="{x:Type local:clsPatients}">
<ObjectDataProvider.ConstructorParameters>
<sys:Boolean>True</sys:Boolean>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
</Window.Resources>
And refer to it in a Binding with the StaticResource markup like this, using the same string we specified in the x:Key attached property we gave it in the dictionary:
{Binding Source={StaticResouce bindingPatients}, Mode=OneWay}
Edit 2: Ok, you posted more code in your answer, and now I know why it's throwing an exception during the constructor. You're attempting to do this...
lstWaitingPatients.DataContext = oPatients;
... but lstWaitingPatients doesn't actually exist until after this.InitializeComponent() finishes. InitializeComponent() loads the XAML and does a bunch of other things. Unless you really need to do something before all of that, put custom startup code after the call to InitalizeComponent() or in an event handler for Window's Loaded event.
The following sets the ItemsSource in Code Behind and correctly handles the DataBinding:
public partial class MainWindow : Window
{
public MainWindow()
{
clsPatients oPatients = new clsPatients(true);
//assuming oPatients implements IEnumerable
this.lstWaitingPatients.ItemsSource = oPatients;
And the XAML:
<ListBox x:Name="lstWaitingPatients"
IsSynchronizedWithCurrentItem="true"
ItemTemplate="{StaticResource WaitingPatientsItemTemplate}"
FontSize="21.333" Height="423.291"
ScrollViewer.VerticalScrollBarVisibility="Visible"
GotFocus="lstWaitingPatients_GotFocus"
/>
Now, I can't get this to work...I get a general Windows startup error.
Here is the codebehind with the Initializer and the class being instantiated:
public partial class MainWindow : Window
{
ListBox _activeListBox;
public MainWindow()
{
clsPatients oPatients = new clsPatients(true);
lstWaitingPatients.DataContext = oPatients;
this.InitializeComponent();
Here's the top of my XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Orista_Charting"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
x:Class="Orista_Charting.MainWindow"
x:Name="windowMain"
Title="Orista Chart"
Width="1024" Height="768" Topmost="True" WindowStartupLocation="CenterScreen" Activated="MainWindow_Activated" >
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/ButtonStyles.xaml"/>
<ResourceDictionary Source="Resources/OtherResources.xaml"/>
<ResourceDictionary Source="Resources/TextBlockStyles.xaml"/>
<ResourceDictionary Source="Resources/Converters.xaml"/>
</ResourceDictionary.MergedDictionaries>
Here's the pertinent XAML, as you see, I went ahead and moved the DataContext down to the ListBox from the StackPanel. This doesn't run, but it does render in Design View (however, with no data present in the ListBox):
<!-- Waiting Patients List -->
<Border BorderThickness="1,1,1,1" BorderBrush="#FF000000" Padding="10,10,10,10"
CornerRadius="10,10,10,10" Background="#FFFFFFFF" Margin="15.245,187.043,0,41.957" HorizontalAlignment="Left" >
<StackPanel x:Name="stkWaitingPatients" Width="300" Margin="0,0,0,-3">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Waiting Patients:" VerticalAlignment="Center" FontSize="21.333" Margin="0,0,0,20"/>
<TextBlock HorizontalAlignment="Right" Margin="0,0,38.245,0" Width="139" Height="16"
Text="Minutes Waiting" TextWrapping="Wrap" Foreground="#FF9C2525" FontWeight="Bold" VerticalAlignment="Bottom"
TextAlignment="Right"/>
<!-- Too be implemented, this is the wait animation -->
<!--<Image x:Name="PollGif" Visibility="{Binding Loading}"
HorizontalAlignment="Left" Margin="100,0,0,0" Width="42.5" Height="42.5"
Source="Images/loading-gif-animation.gif" Stretch="Fill"/>-->
</StackPanel>
<ListBox x:Name="lstWaitingPatients"
DataContext="{Binding Mode=OneWay}" ItemsSource="{Binding Mode=OneWay}"
IsSynchronizedWithCurrentItem="true"
ItemTemplate="{StaticResource WaitingPatientsItemTemplate}"
FontSize="21.333" Height="423.291" ScrollViewer.VerticalScrollBarVisibility="Visible"
GotFocus="lstWaitingPatients_GotFocus"
/>
</StackPanel>
</Border>
Ok, but if I just take comment out the assigment line in the codebehind, it does run (albeit with no data in the listbox):
public partial class MainWindow : Window
{
ListBox _activeListBox;
public MainWindow()
{
clsPatients oPatients = new clsPatients(true);
//lstWaitingPatients.DataContext = oPatients;
THANKS!

WPF binding user control with data in C# code

I've create user control like this:
public partial class View
{
public View()
{
InitializeComponent();
}
public static DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(TeaserView) );
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
}
XAML:
<UserControl x:Class="Controls.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="200" Width="164">
<Grid VerticalAlignment="Stretch"
x:Name="Preview">
<Label Height="28" Content="{Binding ElementName=Preview, Path=Name}" Background="LightYellow" x:Name="name" VerticalAlignment="Top" ></Label>
</Grid>
</UserControl>
and use it in Window1 simply in XAML:
<controls:View Height="200" Name="View1" Width="164" />
and I try set the Content in C# (Name property in this sample) but it does'n work, label's content is still empty. (All refereces, etc. are good) What's wrong?
Your code is wrong. You bind to Grid.Name property, which is "Preview", not to View.Name.
I really encourage you to go read from A to Z "DataBinding Overview" on MSDN. It worth your time, trust me :). In fact whole "Windows Presentation Foundation" section would be worth your attention.
As for your code, the following will work:
<UserControl x:Class="WpfApplication5.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300"
Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Label Height="28"
Content="{Binding Path=Name}"
Background="LightYellow"
VerticalAlignment="Top"/>
</Grid>
</UserControl>
But are you sure you want to hide "Name" property from parents?
Have you set the datacontext on the user control? Try setting it to point to its own codebehind:
DataContext="{Binding RelativeSource={RelativeSource Self}}"
I've put the Name property just as sample. I'm trying to set Label Content in Window1.xaml.cs like:
View1.Name = "Casablanca";
Try the following binding, it should work:
<Label Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:View}}, Path=Name}" />
You should also define a xmlns:local="whatever_path_you_have" on the top of the file.
I also suggest renaming "Name" DP to something else to avoid name collusion.
Copied your exact code and it works fine.
However, it's not doing what you're probably expecting it to do. You're setting the source of the binding to the Grid instance. Therefore, the Name property will yield "Preview". The Name property you've defined in your UserControl is ignored because there's already a Name property on UserControl.

Resources