2
<Button Margin="222,256,130,19" Content="Add" Command="{Binding AddCustomer}">
   <Button.CommandParameter>
      <MultiBinding Converter="{StaticResource MyMultiConverter}">
         <Binding ElementName="Name" Path="Text"></Binding>
         <Binding ElementName="ID" Path="Text"></Binding>
      </MultiBinding>
   </Button.CommandParameter>
</Button>
public class MultiConverter : IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
   {
      return values;
   }

   // ...
}

I've implemented IMultiValueConverter interface in my Class and Implemented the method Convert, but

When my button command executes the method "AddCustomer" it results in the command parameter ending up as object[] { null, null }.

I haven't found an explanation as to why I have to put return values.Clone(); in order to fix this issue

Enlight
  • 65
  • 1
  • 5
  • Good source of information about bindings is your Output window, check there for more info if your bindings work, also you can use `PresentationTraceSources.TraceLevel=High` to get even more accurate information, which will appear in Output window. – XAMlMAX Nov 02 '20 at 10:09

1 Answers1

2

Does the binding return null (as your title claimed before my edit) or does it return a two-element array { null, null } (as your post claims)? The former seems unlikely. The latter can happen if the individual bindings are incorrect.

But, the other thing that will happen is if you are actually returning the values array, that's not an array you own, nor can rely on. As an optimization, WPF reuses the same array each time the converter is called, and the elements of the array are cleared after the converter returns.

That cloning the array fixes the problem is consistent with this behavior. The answer is very simple: don't try to use that array; it's not yours. If you want all the values verbatim, you have to copy to a new array, just as you're doing now.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • https://stackoverflow.com/questions/10759523/using-imultivalueconverter-to-pass-multiple-commandparameters-to-viewmodel . It returns a two element array as null. this post had the same issue, and they explained it briefly, but I did not understand why I had to copy it. The Convert method is run every time the binding value changes. The values of the of the array are there when the Convert method is called, but not when I execute the command. Does it clear the array after.. I execute the command? Why does it clear the array? Shouldn't it return the values first? – Enlight Nov 02 '20 at 12:38
  • _"Does it clear the array after"_ -- yes. _"Shouldn't it return the values first?"_ -- it does return the values...they are there when the converter is called. That is your opportunity to copy the values, if you want to preserve them. Many converters combine the values into some new computed value...whether to copy depends on how the values will be used, but in your case, you (apparently) want to keep the original values passed to the converter, so it's up to you to copy them to someplace safe (e.g. a clone of the array). – Peter Duniho Nov 02 '20 at 17:00
  • So.. If I understand this correctly, the converter is called every time a value is changed in the Textbox, and we're saying ```return values;```. But to where does it return the values? To the CommandParameter property? In that case isn't it preserved in that property even after it clears the array and we execute the command? Or is it preserved but since we're clearing the array, and that's a reference type, the values inside of the CommandParameter also vanish, and that's why we've got to copy them? – Enlight Nov 02 '20 at 17:22
  • 1
    The converter's `Convert()` method is called any time any of the source bindings for the multibinding changes. The values provided by those source bindings are passed as the values in the `values` array. Your converter then is tasked with _converting_ those values to something useful and then _returning_ that value. You are returning the reference to the original `values` array, so that's the value the converter provides in the multibinding, and thus is the value passed to your command. But it's just a reference. By the time the _reference_ is passed to the command, the _values_ in the ... – Peter Duniho Nov 02 '20 at 17:32
  • 1
    ... array have been changed to nulls. It's important to keep in mind that the value your converter is returning is a _reference_ to an object, so any modifications to that object made after the converter returns, are still seen by any code that later uses that _reference. You may want to read questions like https://stackoverflow.com/questions/5057267/what-is-the-difference-between-a-reference-type-and-value-type-in-c and https://stackoverflow.com/questions/1938301/reference-types-in-depth – Peter Duniho Nov 02 '20 at 17:32
  • Right, I was getting confused. object[] array is a reference type, and thus any changes made to it will affect anything that's using its values. However the values of that object array can be reference or value types. Thanks for the wake up explanation. However, if I do something like ```return values[1]``` that would work fine. If it's resetting the object[] array to null, wouldn't that have gotten affected as well? [1] is a string type, and aren't strings reference-types? – Enlight Nov 02 '20 at 17:51
  • Setting the array element to `null` has no more effect on the object that element referenced, than would something like `string s1 = "foo"; string s2 = s1; s1 = null;` result in `s2` being set to `null. The `s2` variable in that example will still refer to the string object having the value `"foo"`, and likewise if you copy the reference from the `values` array, no change to that array can later affect your _copy_ of the reference. It will still refer to the same object it always has. – Peter Duniho Nov 02 '20 at 18:07
  • So, you're saying that when I do ```return values[1]``` it copies the value instead of referencing it..? and thus, when the object[] resets back to null, the value that I returned from the array is still there? – Enlight Nov 02 '20 at 18:24
  • _" the value that I returned from the array is still there?"_ -- yes. Only the array has been modified. Not the things the array referenced. This is fundamental to reference types, so I strongly recommend you review the available reading: [C# language reference](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types), the links I provided above, and of course any number of other discussions about how reference types work. – Peter Duniho Nov 02 '20 at 18:42
  • Ohh! I thought that by setting the array to null, the things that the array is referencing would also be affected. Thank you for the time and explanation. I'll read more on the topic. – Enlight Nov 02 '20 at 18:51