Silverlight MVVM Implementation not Displaying Content - c#

EDIT:
The problem was that my View Models were not public, so the bindings were not found. For some reason they need to be public in Silverlight, even though private view models work for WPF. More detail in my answer below.
I am trying to implement an MVVM WPF app in Silverlight, but I have never used Silverlight before. I am struggling to get the bound content to display. I am implementing it almost exactly how I did with WPF, except that the Main bit is a UserControl, not a Window, the app is hosted by a Web Site, and I had to remove the x:Type in DataTemplate DataType
My Website-to-MainPage is working properly, because I can display a text box or something in that page, however the Binding is just not displayed. Any suggestions?
My MainPage.xaml.cs:
public partial class MainPage : UserControl
{
private MainPageViewModel _viewModel;
public MainPage()
{
InitializeComponent();
_viewModel = new MainPageViewModel();
this.DataContext = _viewModel;
}
}
My MainPage.xaml:
<UserControl x:Class="TransformationServices.Silverlight.MainPage"
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" d:DesignHeight="300" d:DesignWidth="400"
xmlns:view="clr-namespace:TransformationServices.Silverlight.View"
xmlns:viewModel="clr-namespace:TransformationServices.Silverlight.ViewModel"
xmlns:local="clr-namespace:TransformationServices.Silverlight"
Background="#FF2D2D30">
<UserControl.Resources>
<local:ViewConverter x:Key="viewConverter"/>
<DataTemplate DataType="viewModel:InputSelectViewModel">
<TextBlock Text="Hello World!"/>
<!-- This textblock is just for testing. It doesn't work, and neither does the following line-->
<view:InputSelect/>
</DataTemplate>
</UserControl.Resources>
<ContentControl Content="{Binding CurrentView}" />
</UserControl>
My MainPageViewModel.cs
class MainPageViewModel : ViewModelBase, INotifyPropertyChanged
{
private ViewModelBase _currentView;
private List<ViewModelBase> _viewModels;
private int _viewIndex;
public ViewModelBase CurrentView
{
get { return _currentView; }
set
{
if (value != _currentView)
{
_currentView = value;
OnPropertyChanged("CurrentView");
}
}
}
public MainPageViewModel()
{
_viewModels = new List<ViewModelBase>();
// Add view models here
_viewModels.Add(new InputSelectViewModel());
_viewIndex = 0;
CurrentView = _viewModels[_viewIndex];
}
}

It would appear as though the problem is that my ViewModels were not public. I noticed in the Output the following type of message:
System.Windows.Data Error: Cannot get '<Whatever property of View Model>' value ...
This message was coming up for every property that I was binding to, including CurrentView. After making the View Models public, the bindings worked perfectly. It seems odd to me that Silverlight would need the classes to be public when they worked fine as private for WPF, but this is my first time working with Silverlight, so this intricacy tripped me up. Hopefully this answer can help someone in the future. Anyway, this is the main reason for why the bindings were not working, and thus the CurrentView was not being displayed.
Another reason that it was hard for me to debug this issue is that my page was accidentally caching everything, so some of my changes would not display. This link helped me with that:
http://www.codeproject.com/Articles/143414/Prevent-your-Silverlight-XAP-File-from-Caching-in

Related

How to bind to a model in ListView instead of property in WinUI3?

I am trying to directly bind to a model (similar to the situation here), instead of the property on that model, but it is not working. I previously asked a question about this, and the answer had worked in UWP. I am now working in WinUI3 (packaged UWP) and am not sure if the same solution applies.
I have a class:
public class Message
{
public string Title { get; set; }
public string Content { get; set; }
}
I have a UserControl that displays that class:
public sealed partial class MessageControl : UserControl
{
/// <summary>
/// The message to display.
/// </summary>
public Message Message { get; set; }
public MessageControl()
{
this.InitializeComponent();
}
}
With XAML:
<UserControl
x:Class="MessageClient.Controls.EmailControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MessageClient.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<StackPanel>
<!-- Displays the title of the message. -->
<TextBlock Name="HeaderTextBlock"
Text="{x:Bind Message.Title, Mode=OneWay}"></TextBlock>
<!-- Displays the content of the message. -->
<TextBlock Name="ContentPreviewTextBlock"
Text="{x:Bind Message.Content, Mode=OneWay}"></TextBlock>
</StackPanel>
</Grid>
</UserControl>
Now, I have a Window I am displaying that control on, inside of a list view:
<Window
x:Class="MessageClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:EmailClient"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:MessageClient.Controls" xmlns:models="using:MessageClient.Models"
mc:Ignorable="d">
<Grid>
<!-- The list of messages. -->
<ListView x:Name="MessagesListView"
ItemsSource="{x:Bind Messages}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Message">
<controls:MessageControl Margin="5"
Message="{x:Bind Mode=OneWay}"></controls:MessageControl>
<!-- TEST 1 -->
<!--<TextBlock Text="{x:Bind Title}"></TextBlock>-->
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!-- TEST 2 -->
<!--<controls:MessageControl Message="{x:Bind TestMessage, Mode=OneWay}"></controls:MessageControl>-->
</Grid>
</Window>
And the code behind for the Window is:
public sealed partial class MainWindow : Window
{
public ObservableCollection<Message> Messages;
public Message TestMessage;
public MainWindow()
{
this.InitializeComponent();
// Populate the test message.
this.PopulateTestMessages();
}
private void PopulateTestMessages()
{
// The TestDataGenerator just returns a staticaly defined list of test messages.
this.Messages = new ObservableCollection<Message>(TestDataGenerator.GetTestMessages(10));
this.TestMessage = this.Messages.First();
}
}
When I run this code (which compiles and runs), I get a window with the expected number of items in the ListView (10), but they are all blank. There are also no XAML binding failures being reported (via the new feature in Visual Studio 2022). In an attempt to investigate this, I added in a textblock inside of the listview (denoted as TEST 1 in the comments) bound to the Title property of the Message. This worked as expected, displaying the correct titles for the 10 messages. I then added a single MessageControl to the Window outside of the ListView (denoted as TEST 2 in the comments) bound to a single Message property on the Window. This also worked exactly as expected.
Am I missing something? Why does the specific case of binding to a model directly (as opposed to a property on that model - i.e. a binding with no path) not work, when the data is there and works with other binding configurations?
Turns out this specific case exposes some of the ordering of how bindings work in XAML. To understand what is happening here:
The Window is being initialized, which initializes its UI, including the ListView.
The Message models are then retrieved and added to the ObservableCollection.
When each Message is added to the ObservableCollection, the ListView using that ObservableCollection as its ItemsSource then creates a new Item using the ItemTemplate specified in the XAML, and then initializes and binds the newly initialized MessageControl to the Message. The TEST 1 verifies this is happening.
The problem here is in step 3: The MessageControls are initialized AND THEN bound to. When the binding happens, the UI is never notified that it needs to update the binding. This is why adding Mode=OneWay to the {x:Bind} doesn't fix the issue. The OneWay mode tells the binding to update whenever the model updates... but the XAML is still never aware the model was updated.
I am not entirely sure why this is different than the other two bindings (the TEST 1 and TEST 2 comments), but this seems to be an issue with user-defined types (classes) specifically, and NOT with primitive or built-in type properties (such as string and int).
The fix is to enable the model to inform (or "notify") the UI that is has been updated. This is done be implementing the INotifyPropertyChanged interface. Update the MessageControl to:
public sealed partial class MessageControl : UserControl, INotifyPropertyChanged
{
private Message _message;
/// <summary>
/// The message to display.
/// </summary>
public Message Message
{
get { return this._message; }
set
{
this._message = value;
this.RaisePropertyChanged("Message");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
public EmailControl()
{
this.InitializeComponent();
}
}
A final note: implementing INotifyPropertyChanged MUST be done on the MessageControl for this to work. Implementing INotifyPropertyChanged on the Message model would allow for the MessageControl (or any other data bound UI, such as the commented TEST 1) to update if a particular property of the Message model updates, but does not fix the issue of the Message model iself on the MessageControl being updated.

WPF C# Binding Data from another Class

So I'm missing something simple or losing my mind. I am trying to reuse a class for multiple pages in a WPF application and bind the properties to the pages that instance it. I've tried setting the DataContext but I'm missing something. I'm loading the StockAnalysis page and then creating instance of the PriceChart class (this is the class for reuse) and I want the properties set in the PriceChart class to be the data to bind to the Stock.xaml.cs page. Even in setting the DataContext it is still looking for the StockAnalysis object. Why?
Stock.xaml.cs
public partial class StockAnalysis : Page
{
PriceChart PChart = new PriceChart();
public StockAnalysis()
{
InitializeComponent();
//Load The Data
List<Stock> HistoricalPrice = Database.GetPrices(ticker);
//Create The Charts
this.DataContext = PChart;
PChart.ShowPriceChart(HistoricalPrice);
}
}
Stock.xaml (Look at the Last TexBlock for the Binding of "LastPrice")
<Page x:Class="Stock.StockAnalysis"
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:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
xmlns:local="clr-namespace:Stock"
mc:Ignorable="d"
d:DesignHeight="1000" d:DesignWidth="1200"
Title="Stock Analysis">
<StackPanel x:Name="LastClosePanel" Grid.Row="0" Grid.RowSpan="2" Grid.Column="5" Height="60" VerticalAlignment="Top" Margin="1,0,0,1" Style="{StaticResource LastCloseBackground}">
<TextBlock x:Name="LastCloseText" Foreground="OrangeRed" FontSize="12" HorizontalAlignment="Center" Margin="0,10,0,8">Last Close</TextBlock>
<TextBlock x:Name="LastCloseBind" Foreground="White" FontSize="16" HorizontalAlignment="Center" Text="{Binding LastPrice}"></TextBlock>
</StackPanel>
</Page>
PriceChart.cs (This is where I assign "LastPrice" in hopes to bind it to the TextBlock in stock.xaml.cs)
public class PriceChart
{
public string LastPrice { get; set; }
public void ShowPriceChart(List<Stock> FullList)
{
LastPrice = FullList[0].LastPrice.ToString("C");
//DO OTHER THINGS
}
}
The problem is that PriceChart doesn't implement any change notification. With the current code, this is how things will go when StockAnalysis gets created:
InitializeComponent() will create the TextBlocks and the binding. At this point, DataContext is null, so the binding will fail and the TextBlock stay empty.
this.DataContext = PChart will trigger a binding update (because DataContext is a DependencyProperty, which means it does support change notification). When the binding updates, it will pull the value of LastPrice, which is currently still empty.
ShowPriceChart will set the value of LastPrice, but because PriceChart doesn't support change notification, the binding doesn't know it needs to update, so the TextBlock stays empty.
To solve this, I would recomend your PriceChart implement the INotifyPropertyChanged interface per this article: How to: Implement Property Change Notification.
(Technically, moving PChart.ShowPriceChart(HistoricalPrice) before this.DataContext = PChart would also "solve" the problem, but only if you never need to update the bindings again after initialization.)

Binding button command to different ViewModel

I think I might be doing something totally wrong here, so hopefully you guys can correct me.
I want to switch Views (switch UserControls inside a Window) using a button, then have the other View be able to have a button that switches back to the first View (like a back button). I've found how to do this using the Google, but the problem I'm running into is that I have my first View's DataContext bound to one ViewModel and the code for switching views is in another, so I can't seem to bind the button in the first View to Bind its Command to that other ViewModel. Here's what I mean (simplified):
FirstView.xaml.cs:
private readonly FirstViewModel viewModel = new FirstViewModel();
public AirplanesStatusView()
{
InitializeComponent();
DataContext = viewModel; //Bound to this viewModel for other reasons
}
FirstView.xaml:
<UserControl>
<Grid>
<Button Command="{Binding GotoSecondViewCommand}}" //This Command is in other MainWindowViewModel
</Grid>
</UserControl>
MainWindow.xaml.cs:
private readonly MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = mainWindowViewModel;
}
So then from what I found on Google, this is how it said to approach switching Views:
MainWindow.xaml:
<Window>
<Window.Resources>
<DataTemplate DataType="{x:Type local:FirstViewModel}">
<local:FirstView/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:SecondViewModel}">
<local:SecondView/>
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding CurrentView}" />
</Window>
MainWindowViewModel.cs:
private ICommand _gotoFirstViewCommand;
private ICommand _gotoSecondViewCommand;
private object _currentView;
public ICommand GotoFirstViewCommand{ //stuff }
public ICommand GotoSecondViewCommand{ //stuff }
public object CurrentView
{
get { return _currentView; }
set
{
_currentView = value;
OnPropertyChanged("CurrentView");
}
}
The problem is when I run the program, in the output it says "System.Windows.Data Error: 40 : BindingExpression path error: 'GotoSecondViewCommand' property not found on 'object' ''FirstViewModel', so the Button can't even find the command. I'm pretty sure I'm doing something totally wrong as I'm pretty new to WPF and the MVVM patter. Help and correction would be greatly appreciated.
Try this:
<Button Command="{Binding DataContext.GotoSecondViewCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>
It binds to the DataContext of the parent window, i.e. the MainWindowViewModel where the GotoSecondViewCommand is defined.
You are binding wrong ViewModel as DataContext. Based on you structure, you need to do...
Take Command for the Button in FirstViewModel for moving to SecondView.
Take Command for the Button in SecoondViewModel for moving to FirstView.
Remove command from MainViewModel because it is of no use.
Put relative business logic in command execution to transfer the views.
Your CurrentView is nothing but the current user control (either FirstView / Second View)
Another way is if you want to take command in MainViewModel
Take only one ICommand as "ChangeViewsCommand"
Detect the current View either FirstView / Second View) from CurrentView
Transfer to another view which is not active.

Binding Simple WPF TextBox Text TwoWay

I am very sorry that this question is very basic. I just learned WPF and I failed to make simple two way binding to textbox.text to string property.
XAML Code:
<Window x:Class="WpfApplication1.MainWindow"
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"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="StuInfo">
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="10,26,0,0" TextWrapping="Wrap" Text="{Binding Path=str,Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button" Content="Check" HorizontalAlignment="Left" Margin="10,67,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
C# Code
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
str = "OK";
}
public string str { get; set; }
private void button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine(str);
}
}
First, the textbox does not show "OK", but it is blank. Then, I typed a different text into the textbox, for ex:"blablabla" without the quotes. Then I click the button to check if my str property has been updated. Apparently, str still contains "OK".
What did I do wrong here? What did I miss to make the binding work?
As a newcomer to WPF, all this Binding and DataContext jazz can be quite confusing. Let's start with your binding expression first...
<TextBox Text="{Binding Path=str, Mode=TwoWay}"/>
What this is saying is that you want to bind your Text property to whatever the DataContext of the TextBox is. DataContext is essentially the "thing" your TextBox is getting it's data from. Now here's the rub. DataContext is inherited from the element "above" it in the visual tree if not explicitly set. In your code, TextBox inherits it's DataContext from the Grid element, which in turn inherits it's DataContext from the Window element. Seeing that DataContext is not set in your Window the default value of the DataContext property will be applied, which is null. The DataContext is also not set in any of the child elements of your window, which, via inheritance, will set the DataContext of all children of that window to null.
It is important to note that you've left out the Source property in your binding expression.
<TextBox Text="{Binding Source=left_out, Path=str, Mode=TwoWay}"/>
When this property is left out, the binding's source is implied to be the elements DataContext, which in this case is null, for the reasons mentioned above. Basically, what your expression is saying here is that you want to bind your text property to DataContext.str which resolved by WPF is null.str.
OK, cool. Now, how do we set the DataContext of your TextBox.Text binding to the Code Behind for the window so we can get at that str property? There are several ways to do this, but for our purposes we'll focus on setting it explicitly in the binding of the TextBox.Text property. Now, there are three different "source" type properties of bindings. "Source" being where we want our control/element's binding to get it's data from. We have Source, RelativeSource, and ElementName. We're only going to focus on ElementName here, but the others are essential to research and understand.
So, let's name our Window element so we can access it through the ElementName property.
<Window x:Class="WpfApplication1.MainWindow"
x:Name="_window"
...
Now we can set the ElementName property on the TextBox.Text binding to refer to the window.
<TextBox Text="{Binding ElementName=_window, Path=str, Mode=TwoWay}"/>
This means the binding will look for the _window.str property when trying to resolve it's binding. At this point, you still probably won't see your str value reflected in the TextBox. This is because it's value is set after the InitializeComponent method in the window's constructor. This function is where bindings are resolved for the first time. If you were to set the value of str before calling InitializeComponent, you would see the value reflected in the TextBox.
This brings us to Dependency Properties. For now, just know that Dependency Properties have built in change notification, which your binding needs so it "knows" when the binding has changed and when to resolve the binding value again. Yes, you could use INotifyPropertyChanged in your code behind, but there are good arguments for using DependencyProperties in this case, which will only confuse the issue at this point. But, it is another one of those things that is essential to understand.
Here is the code for a DependencyProperty for your str property.
public static readonly DependencyProperty StrProperty
= DependencyProperty.Register("Str", typeof(string), typeof(MainWindow),
new FrameworkPropertyMetadata(FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string Str
{
get{return (string)GetValue(StrProperty);}
set{SetValue(StrProperty,value);}
}
Now you'll be able to set the value like such and have it reflect through the binding to your TextBox.
public MainWindow()
{
InitializeComponent();
Str = "OK";
}
At this point, all should be well. I hope this helps out. It took me a while get the hang of WPF. My suggestion would be to read as much as you can on DataContext, Binding, and DependencyProperty as these are the core of WPF. Good luck!
The problem is that, you dont bind to codebehind of Window, but to DataContext.
Try this:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new DC();
}
public class DC
{
public string str { get; set; }
public DC()
{
str = "OK";
}
}
}
Normally, you would have two different files, but for test, you can do it in one file.
After that, your DC (DataContext) should implement INotifyPropertyChanged interface.
Try to find some article about MVVM like this http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial

Disappearing UserControl after build

The Issue: I have a newly made UserControl with a couple telerik controls in a parent Grid to be able to use it throughout the solution. Sounds simple enough right? I created the UserControl, let's call the Class My.Project.Controls.Tool, which I then tried to call to another View with the namespace xmlns:Controls="clr-namespace:My.Project.Controls;assembly=My.Project.GlobalUserControlDump" and then set it in the view via easily selected from the handy dandy intellisense.
This does as is expected, my UserControl appears on the separate view in the designer just fine. So I take the next normal step and build it....as soon as the build completes (which it does just fine with no errors reported as expected) the little bugger disappears! The xaml is still on the View of course, but it's disappeared from the designer AND it doesnt appear on the built solution?
Confused I go back, make a quick change to the UserControl and it appears back in the designer. Ok, I think it must be some fluke so I build it again....and again it disappears from the designer AND the built solution?
Now I can continue to reliably reproduce this scenario. Make a little change to the UserControl, it re-appears in the designer.....then build it and it disappears again!
Could someone pretty please shed some light on this quandry? Running in SL (both in and out of browser but built in browser) with Caliburn Micro. Any insight to this mystery is of course greatly appreciated, hoping another pair of eyes can catch my folly. Cheers!
For Clarification, this is what sits in the user control that directly related to a previous question.
<UserControl
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"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable="d"
x:Class="My.Project.Controls.DatePicker">
<Grid Width="90">
<telerik:RadDateTimePicker
InputMode="DatePicker"
SelectedDate="{Binding SelectedDate, Mode=TwoWay}"/>
<telerik:RadMaskedDateTimeInput
IsClearButtonVisible="False"
FormatString="{}{0:M/d/yy}"
SelectionOnFocus="SelectAll"
Value="{Binding SelectedDate, Mode=TwoWay}"/>
</Grid>
</UserControl>
Which I would then invoke directly on a view like (It would sit in the GlobalUserControlDump project as the namespace shows) and once the namespace is added to the View, it shows up fine in the intellisense as expected;
<UserControl
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"
xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
x:Class="My.Project.Views.RandomView"
xmlns:Controls="clr-namespace:My.Project.Controls;assembly=My.Project.GlobalUserControlDump"
mc:Ignorable="d">
<Grid>
<Controls:DatePicker />
</Grid>
</UserControl>
Then I'm exposing the property I need via;
namespace My
{
public partial class DatePicker : UserControl
{
public static readonly DependencyProperty SelectedDateProperty =
DependencyProperty.Register("SelectedDate", typeof(DateTime), typeof(DatePicker), new PropertyMetadata(null));
public DatePicker()
{
// Required to initialize variables
DataContext = this;
}
public DateTime SelectedDate
{
get { return (DateTime)GetValue(SelectedDateProperty); }
set { SetValue(SelectedDateProperty, value); }
}
}
}
Thanks for taking a look, has me still currently stumped.
You are missing a call to InitializeComponent() in you UserControl's constructor.
I believe your namespace in the code you posted is incorrect.
By having new PropertyMetadata(null)); a property changed callback isn't being registered. Without that I believe binding won't work. What you want to do is bind to the property on your usercontrol and when the bound value changes, you want to set the value on the RadDateTimePicker contained in your control.
xaml:
<Grid Width="90">
<telerik:RadDateTimePicker x:Name="MyRadDateTimePicker" InputMode="DatePicker" />
<telerik:RadMaskedDateTimeInput x:Name="MyRadMaskedDateTimeInput"
IsClearButtonVisible="False"
FormatString="{}{0:M/d/yy}"
SelectionOnFocus="SelectAll" />
</Grid>
</UserControl>
code behind:
using System;
using System.Windows;
namespace SO
{
public partial class MyDatePicker
{
public MyDatePicker()
{
InitializeComponent();
}
public const string SelectedDatePropertyName = "SelectedDate";
public DateTime SelectedDate
{
get { return (DateTime)GetValue(SelectedDateProperty); }
set { SetValue(SelectedDateProperty, value); }
}
public static readonly DependencyProperty SelectedDateProperty = DependencyProperty.Register(
SelectedDatePropertyName,
typeof(DateTime),
typeof(MyDatePicker),
new PropertyMetadata(DateTime.Now, OnSelectedDatePropertyChanged));
private static void OnSelectedDatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MyDatePicker)d).MyRadDateTimePicker.SelectedDate = (DateTime) e.NewValue;
((MyDatePicker)d).MyRadMaskedDateTimeInput.Value = (DateTime)e.NewValue;
}
}
}

Categories