Reputation: 1761
I have a grid with a rectangle in each cell in the xaml. I know I can bind the fill of each rectangle to a property in my ViewModel, but I want to instead bind the fill of each rectangle to a method in the ViewModel and pass in the x- and y- coordinates of the rectangle, and get back the fill (which can change during runtime).
Is there an easy way to do this? I don't know if this is even possible, since when the method changes the fill it returns for a particular x- and y- coordinate, how would the view know that the method updated that value?
The problem I'm facing is that since the ViewModel doesn't know about any of the UI controls on the View, I can't just directly change the fill colors on the rectangles. Also, since the grid can be large, I can't have a separate property for each rectangle.
Upvotes: 0
Views: 869
Reputation: 7517
This may not work in your scenario, but you can invoke a method from a binding using an ObjectDataProvider. Here's a quick example:
<Window.Resources>
<local:StringToDoubleConverter x:Key="stringToDouble" />
<local:MyObject x:Key="objInstance" />
<ObjectDataProvider
x:Key="odp"
ObjectInstance="{StaticResource objInstance}"
ObjectMethod="MyMethod"
>
<ObjectDataProvider.MethodParameters>
<sys:Double>0</sys:Double>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
Now, an element in your view, say a TextBox can bind to the method parameter:
<TextBox Text={Binding Source={StaticResource odp}, Path=MethodParameters[0], UpdateSourceTrigger=PropertyChanged, Converter={StaticResource stringToDouble}} />
The method return value can then be used in a binding elsewhere:
<Label Content="{Binding Source={StaticResource odp}}" ContentStringFormat="Method returned: {0}" />
Again, this may not work in your scenario, but it does illustrate a way to pass a parameter to a method and use the return value entirely in XAML. Here's a resource for more information: http://bea.stollnitz.com/blog/?p=22
Upvotes: 1
Reputation: 7573
You could try using an IValueConverter
for this:
[ValueConversion(typeof (MyCoordObject), typeof (Brush))]
public class CoordToBrushConverter : ConverterExtension
{
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var coordObject= (MyCoordObject) value;
if (coordObject.X == 132) return Brushes.Red;
//define your own brushes as StaticResource or something, this won't work
return Brushes.Black;
}
public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
//nothing
return value;
}
}
Now you just have to figure out which object you wanna pass to the converter. Use this in your XAML like this:
<my:CoordToBrushConverter x:key="myConverter"/>
<TextBox BackgroundBrush={Binding myObj, Converter={StaticResource myConverter}} />
If you don't have an object which contains to coordinates, maybe you can use a MultiValueConverter and pass the coordinates one by one from the control? You should play around with this to get it to work probably.
If you don't wanna use converters, you could always check out some of the MVVM frameworks out there, if I'm not mistaken some of them support binding to methods.
Check Caliburn or MVVMLight
HTH
Upvotes: 0
Reputation: 70142
Binding cannot be used as a way to invoke methods and pass parameters. It is merely a mechanism for synchronising state between your view and your view model.
In your case, the view model needs to know the coordinates of your rectangle in order to determine the fill. Therefore, for each rectangle, your view model needs to expose X, Y, Fill
properties.
The big problem here is how to supply the view model with the X & Y coordinates? I am guessing these rectangles are within some sort of container that dictates their location? If so, the only technique I can think of is to create an attached behaviour for a UIElement that calculates its position via TransformToVisual. See for example:
http://forums.silverlight.net/forums/p/12160/414862.aspx
This can then be bound to your X & Y values in your view model.
However, to be honest, if you struggle to get MVVM working here, perhaps it is the wrong pattern?
If you are just building a UI which is composed of coloured rectangles, I would just do it in a loop, adding Rectangles and colouring them in code-behind!
KISS (Keep It Simple Stupid!)
Upvotes: 0