|
I've got a 3rd party control:
class Foo : SomeWPFControl, INotifyPropertyChanged
{
public DateTime Start { get; }
public event PropertyChangedEventHandler PropertyChanged;
}
I slap this control on my view. Then I code up a little ViewModel. All is good.
I need to do work in my ViewModel when the control's Start property changes. How do you recommend doing this?
Attempt #1: I tried creating a DateTime property in my view model, then binding the control's .Start property to my property in the ViewModel, but that didn't work because "Start is a read-only property". Fail.
Attempt #2: I can listen to control.PropertyChanged inside my view, and when it fires, call some function on my ViewModel. But that doesn't seem very MVVMish. Fail?
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon
Judah Himango
|
|
|
|
|
Have you tried, in the binding, specifying "Mode=OneWayToSource"?
If that doesn't work, then if I'm interpreting this correctly, #2 is probably the way to go.
|
|
|
|
|
Yeah, I still get a compiler error when specifying Mode = OneWayToSource.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon
Judah Himango
|
|
|
|
|
Strange... Might not be set up properly as a DependencyProperty. #2 might be your only option, unfortunately.
|
|
|
|
|
There is a DependencyProperty on the class:
public Foo
{
public static DependencyProperty StartDateProperty;
public DateTime StartDate
{
get { ... }
}
}
The only way to change the StartDate is by clicking a button in the 3rd party control.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon
Judah Himango
|
|
|
|
|
Hmm, strange way of setting it up...
I mean, you could bind another control to that value, but you can't bind the "StartDate" to a CLR object.
Yeah, I don't see a solution here other than hooking PropertyChanged.
|
|
|
|
|
Alright, well that's a legitimate answer, too. Thanks.
I'm mostly a newb when it comes to WPF, and definitely a newb when it comes to MVVM. I just wanted to be sure I wasn't doing things improperly. If this is the only way to make this work, alrighty.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon
Judah Himango
|
|
|
|
|
Yeah, it's not ideal, but you do what you have to do, right?
|
|
|
|
|
Is the Start property in the control readonly? What is the mechanism for updating this property?
"WPF has many lovers. It's a veritable porn star!" - Josh Smith As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.
My blog | My articles | MoXAML PowerToys | Onyx
|
|
|
|
|
The Start property is a readonly .NET property:
public DateTime Start
{
get { ... }
}
There is a static DependencyProperty behind the scenes:
public class Foo
{
public static DependencyProperty StartProperty;
}
Pete O'Hanlon wrote: What is the mechanism for updating this property?
If the user clicks a button in the 3rd party control, the .Start will change.
Religiously blogging on the intarwebs since the early 21st century: Kineti L'Tziyon
Judah Himango
modified on Wednesday, December 9, 2009 5:38 PM
|
|
|
|
|
Hello,
Fairly new to WPF so hope this isn't going to be a case of failing to RTFM but I just can't see what has gone wrong.
I am modifying an existing user control to show slightly different data in a list depending on a setting on the control. I have registered the dependency property, added a get;set to use it else where in code and it comes up in the Intellisense in the XAML file. However it is not set to the value I've set it to in the XAML when it is check in the controls constructor.
Here is the relevant bits of the user control:
public partial class StationGroupControl : UserControl
{
public StationGroupControl()
{
try
{
if (ShowAggregates != true)
...
public static DependencyProperty ShowAggregatesProperty =
DependencyProperty.Register("ShowAggregates",
typeof(Boolean),
typeof(StationGroupControl),
new FrameworkPropertyMetadata(false));
public Boolean ShowAggregates
{
get
{
return (Boolean)GetValue(ShowAggregatesProperty);
}
set
{
SetValue(ShowAggregatesProperty, value);
}
}
And the XAML:
<ResearchCtrl:StationGroupControl Name="MultStation" HorizontalAlignment="Left" Margin="-122,0,0,0" Validation.Error="Ctrl_Error" ShowAggregates="True"></ResearchCtrl:StationGroupControl>
Frustratingly this seemed to be working and I then refactored the code down to smaller chunks and it inexplicably stoppped working. It has me doubting if it was ever working properly.
Is there some issue with using a boolean? Something else I need to do? Any way of debugging what is actually happening?
I'm pushed for time on this so any suggestion gratefully received.
Robert.
|
|
|
|
|
You're testing the value in the constructor, but it's not being set until AFTER.
The XAML is going to first create the object, THEN start setting properties... So basically what's happening is:
1) Object created
2) Constructor fires, checking ShowAggregates value
3) XAML parser sets the Name property
4) XAML parser sets the HorizontalAlignment property
...
7) XAML parser sets ShowAggregates to true
EDIT: Oh, should have added... The solution is to hook the Initialized event, or override OnInitialized, and do the check there.
|
|
|
|
|
Thanks, as suspected if I'd read the "manual" more closely I'd have spotted that eventually, if I wasn't mildly panicking I probably would have.
Thanks again Ian!
|
|
|
|
|
Hello again,
I tried moving the code to the Initialized event but it still wasn't set. I've now moved to the Loaded event and it is there so that's where I've left it for the moment. Let me know if you think this might cause a problem.
Thanks,
Robert.
|
|
|
|
|
|
Hi,
Is there a way in xaml/wpf to freeze first item in listbox from scrolling?
Thanks
|
|
|
|
|
Here is the scenario:
1. Open Visual Studio 2008, create new project...
2. Select WPF Custom Control Library as the project type
3 Open the Generic.xaml resource dictionary located in the Themes folder
4. Add a simple brush such as:
<SolidColorBrush x:Key="BackgroundBrush" Color="Yellow"/>
5. Change the Background property of the nested Borer Control from
Background="{TemplateBinding Background}"
to
Background="{DynamicResource BackgroundBrush}"
Now when you compile and use this control in any project, the background will NOT be yellow. BUT, if you change the background property to be a StaticResource as such
Background="{StaticResource BackgroundBrush}"
...it will work. Why is this? Why does StaticResource work but not DynamicResource???
|
|
|
|
|
Hi,
I am working with a Silver light application with WCF service. In this I have a session variable names "UserId" which will be created in user login.aspx page. Now I need to access this current login UserId into my WCF service.
or
I need to access this UserId sesssion variable in the silver light page and then pass it to WCF service as parameter.
If any one have any idea ti implement any one of the above please reply me.
Thanks in advance.
|
|
|
|
|
|
I have another issue with the WPF Ribbon control when i have two buttons on the bottom of the Application menu button. When i'm running my app and i click on a button on one of my tabs, it pops up with a user dialog for the user to choose then close. The issue i'm having is when the user clicks on any of the buttons in the dialog and then closes it, the two buttons i have in the Application menu button are disabled for some reason until the user clicks on the menu bar again. Why is that? Is this a known issue or just a quirk in WPF Ribbon? Thanks in advance!
|
|
|
|
|
how do i disable the mouse scroll in the WPF ribbon bar?
i'm trying to disable this because of the tabs that i have in my ribbon bar shouldn't be accessed until they are properly called on. This causes issues when the user is able to scroll through the tabs
Any ideas or advice would be much appreciated!
|
|
|
|
|
I have found a solution to this(or maybe a work around, not sure) that does what i want it to do
I found the answer here: http://blogs.infragistics.com/forums/p/6887/28951.aspx[^]
This disables the mouse scroll for when the mouse is over the Ribbon bar which is EXACTLY what i needed!
I replied to my own question so that if others had the same problem they could see this answer i found
|
|
|
|
|
Hi, Im using WPF controls in MFC.IN one dialog i want to get these controls,textbox,button etc.,And for button i wrote function.But it shows error at bolded line as
error C3364: 'System::Windows::RoutedEventHandler' : invalid argument for delegate constructor; delegate target needs to be a pointer to a member function
HWND GetHwnd(HWND parent,CSampleWPF* view,int x, int y, int width, int height)
{
// Create an HwndSource WPF object
System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters ("WPFSourceWindow");
sourceParams->PositionX = x;
sourceParams->PositionY = y;
sourceParams->Height = height;
sourceParams->Width = width;
sourceParams->ParentWindow = IntPtr(parent);
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD;
HwndSource^ source = gcnew System::Windows::Interop::HwndSource(*sourceParams);
view->m_wpfTextBox = gcnew TextBox();
view->m_wpfTextBox->Width=100;
view->m_wpfTextBox->Height=20;
view->m_wpfTextBox->Text = "Some WPF Text";
source->RootVisual = view->m_wpfTextBox;
view->m_Button = gcnew Button();
view->m_Button->Height=60;
view->m_Button->Margin=Thickness(2);
view->m_Button->Background::set(Brushes::SkyBlue);
view->m_Button->Click += gcnew RoutedEventHandler(view->m_Button,&CSampleWPF::OnBtnExit); source->RootVisual = view->m_Button;
return (HWND) source->Handle.ToPointer();
}
void CSampleWPF::OnBtnExit(Object^ sender, RoutedEventArgs^ e)
{
AfxMessageBox(_T("Simple message box."));
}
And also in output,its shows only the button not the textbox.Wats the mistake??
Anu
|
|
|
|
|
Hi Peoples,
I have designed a application in WPF browser aplication template.
I need to Publish/Host the same in the IIS server, means i need to access the same from i.e or mozila browser.
can any one help me? how to do the same ,
Thanks in advance.
|
|
|
|
|
Hi!
I'm kinda new to WPF and there's a lot of way to do stuff, I'm getting a bit mixed up. I would appreciate if someone could check the way I'm trying to do things and tell me what I understood wrong.
I'm trying to have a simple Windows with a grid. The rows in the grid are dynamically filled. I want to have a template for each row so they contain the same controls. I also want to have a feedback on these controls (when the selection of the first combobox change, populate the second combobox differently). And finally, I want to be able to see the selected values for each row controls when the user press the OK button.
Here is my XAML code:
<Window x:Class="WpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication"
Title="MainWindow" Height="300" Width="300">
<Window.Resources>
<DataTemplate x:Key="RowTemplate"
DataType="{x:Type local:RowViewModel}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Variable "/>
<TextBlock Text="{Binding Path=Slot}"/>
</StackPanel>
<ComboBox Grid.Column="1"
ItemsSource="{Binding Path=FirstList}"
SelectionChanged="Combo1SelectionChanged"/>
<ComboBox Grid.Column="2"
ItemsSource="{Binding Path=SecondList}"
SelectionChanged="Combo2SelectionChanged"/>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="MainGrid">
</Grid>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right">
<Button Content="Ok"/>
<Button Content="Cancel"/>
</StackPanel>
</Grid>
</Window>
And my C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace WpfApplication
{
public class List1 : ObservableCollection<string>
{
public List1() : base()
{
Add("A");
Add("B");
Add("C");
}
}
public class List2 : ObservableCollection<string>
{
public List2(string basedOn) : base()
{
Add(basedOn + "1");
Add(basedOn + "2");
Add(basedOn + "3");
}
}
public class RowViewModel : INotifyPropertyChanged
{
private int m_slot = 0;
private List1 m_firstList = null;
private List2 m_secondList = null;
public RowViewModel(int Slot)
{
this.Slot = Slot;
this.FirstList = new List1();
this.SecondList = new List2(Slot.ToString());
}
public int Slot
{
get
{
return m_slot;
}
set
{
if(value != m_slot)
{
m_slot = value;
NotifyPropertyChanged("Slot");
}
}
}
public List1 FirstList
{
get
{
return m_firstList;
}
set
{
if (value != m_firstList)
{
m_firstList = value;
NotifyPropertyChanged("FirstList");
}
}
}
public List2 SecondList
{
get
{
return m_secondList;
}
set
{
if (value != m_secondList)
{
m_secondList = value;
NotifyPropertyChanged("SecondList");
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
for(int i=0; i<10; i++)
{
RowDefinition rowDef = new RowDefinition();
this.MainGrid.RowDefinitions.Add(rowDef);
ItemsControl item = new ItemsControl();
item.DataContext = new RowViewModel(i);
item.SetValue(Grid.RowProperty, i);
this.MainGrid.Children.Add(item);
}
}
private void Combo1SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void Combo2SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
}
My problem currently is that I don't know which type of control to add to the grid because it's probably not a ItemsControl, nor a ContentControl? Also, the "RowTemplate" can't seem to be visible in my C# code, so I can't tell it to use it to display. Another problem is that I don't have access to the viewmodel and combobox directly in my SelectionChanged event, so I can't re-populate my list from there. I should probably do this in a totally different way, but as I said I'm getting mixed up.
|
|
|
|