views:

734

answers:

2

Hi,

I've recently overridden the DevXpress WPF grid to give myself a SelectedObject property that I can access from my loosely bound ViewModel.

I've made a SelectedObject dependency property and have it bound OneWayToSource in my XAML.

Everthing works fine, but if I try to make it ReadOnly (for completeness) I get a compile error and says I can't bind to a ReadOnly property. The code below compiles, I've included (but rem'd out) the bits I've been trying in my attempts to get the property ReadOnly.

Can anyone assist please?

The Dependency Property of my overridden control looks like:

  //public static readonly DependencyPropertyKey SelectedRowKey = DependencyProperty.RegisterReadOnly("SelectedObject", typeof(object), typeof(MyGrid), new PropertyMetadata(null));
//public static readonly DependencyProperty SelectedObjectProperty = SelectedRowKey.DependencyProperty;

public readonly static DependencyProperty SelectedObjectProperty = DependencyProperty.Register("SelectedObject", typeof(object), typeof(MyGrid), new PropertyMetadata(null));

public object SelectedObject
{
    get
    {

        return GetValue(SelectedObjectProperty);
    }
    set
    {
        throw new NotImplementedException();
    }
}

The XAML is:

 <StackPanel>
  <devxgrid:MyGrid AutoPopulateColumns="True" DataSource="{Binding Animals}" SelectedObject="{Binding MyObject, Mode=OneWayToSource}" Width="300" Height="300">
    <devxgrid:MyGrid.View>
        <MyGrid:TableView AllowEditing="False" Name="GridView" AutoWidth="True" />
    </devxgrid:MyGrid.View>
 </devxgrid:MyGrid>
</StackPanel>
+4  A: 

You're trying to set the SelectedObject property in the XAML. If it's read-only, how can you set it?

Edit: sorry, my bad. Just realized what you're trying to do, and you're right that it should work. However, WPF doesn't support this scenario, at least in 3.5.

Edit 2: Just checked in .NET 4 and same story.

By the way, if you're stuck with someone else's readonly DP that you're trying to "push" into a VM, you can use an attached behavior to workaround this. For example, suppose you want your VM to be aware of the ActualWidth and ActualHeight properties of your view. You can write a SizeWatcherBehavior that attaches to the FrameworkElement and listens for size changes. When detected, those size changes are pushed to read/write attached properties that your VM can bind to:

<Grid local:SizeWatcherBehavior.Watch="True"
    local:SizeWatcherBehavior.Width="{Binding WidthOnVM, Mode=OneWayToSource}"
    local:SizeWatcherBehavior.Height="{Binding HeightOnVM, Mode=OneWayToSource}"/>

HTH,
Kent

Kent Boogaart
Thanks for your help Kent - unfortunately I don't think I can use the watcher at theres no DP to use, but its good to know such things exist! My program works anyway, I just hate leaving that 'throw new NotImplementedException();' - its not a 'broken window' but its not far off! but thanks a lot for looking into to it.
Andy Clarke
I think this is a serious issue with WPF and adopting the MVVM pattern. When the source property is read-only you're allowed to define OneWay bindings, which is great. But when the target DP is read-only you're not allowed to define OneWayToSource bindings. I don't really understand why not..
Oskar
And I'm really frustrated to hear this is not going to be supported in .NET 4 either.
Oskar
For reference, I filed an issue for this and got some feedback today. It is not supported per design, and won't be in the nearest future. https://connect.microsoft.com/WPF/feedback/ViewFeedback.aspx?FeedbackID=523865
Oskar
A: 

We are developing a custom control library, and one of our users filed a feature request to convert one of our DPs from Read-Only to Read-Write, because he did hit the same issue as you did - cannot bind OneWayToSource in an MVVM scenario.

Of course we did not make that DP read-write.

Using attached properties/behaviors for such scenarios is a huge overhead. The simplest workaround would be to handle the "SelectedObjectChanged" event in the code behind, and set the property that you wanted to bind to "SelectedObject" DP in the code behind.

In our opinion, this 'handle the event and call code from VM/DataContext directly' approach does not break MVVM in any way, since the ViewModel still does not know anything about the View.

Ugur Turan