Search code examples
windows-store-appswinrt-xamlprism

DelegateCommand<T> Exception When Binding in DataTemplate


I think I've found a bug in the Prism for Windows Runtime library, but I'd like to know if there's a work around or a way to fix the issue without forking the project myself...

I'm trying to display a list of items in an ItemsControl. Each item has a button, which when clicked should execute a command on the parent control's data context and pass the item's ID as the command parameter. Basically, I'm trying to render a list of items and have a delete button for each item. To accomplish this, I'm following this code sample, which I've so far found as the only clean way to accomplish this feat.

Unfortunately, the DelegateCommand<T> class implemented by Prism for Windows Runtime seems to not play well with the XAML binding parser. When everything is hooked up, I receive this exception when the page tries to render:

Failed to assign to property 'Windows.UI.Xaml.Controls.Primitives.ButtonBase.Command'. [Line: 61 Position: 49]

I created a new project and simplified my production example to test my theory that this is an issue with DelegateCommand<T> (which is needed to allow a parameter to be passed to the delegate method). I implemented two commands, one using DelegateCommand<T> and one just using DelegateCommand. The one using DelegateCommand doesn't cause an exception, but I lose the ability to accept a command parameter which means I can't identify which item was to be deleted.

The XAML:

<ItemsControl Name="TestControl" Grid.Row="1" ItemsSource="{Binding MyItems}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding}" Command="{Binding DataContext.BrokenCommand, ElementName=TestControl}" CommandParameter="1" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

The View Model:

public DelegateCommand<int> BrokenCommand { get; set; }
public DelegateCommand WorkingCommand { get; set; }

public List<string> MyItems { get { return new List<string> {"A", "B", "C"}; } }

public MainPageViewModel(INavigationService navigationService)
{
    BrokenCommand = new DelegateCommand<int>(BrokenMethod);
    WorkingCommand = new DelegateCommand(WorkingMethod);
}

private void BrokenMethod(int i)
{
    throw new NotImplementedException();
}

private void WorkingMethod()
{
    throw new NotImplementedException();
}

Solution

  • try this

        BrokenCommand = new DelegateCommand<string> 
        (id => BrokenMethod(Convert.ToInt32((id));
    

    I just tested it, and it works if you change your T to string as it comes as a string.

    Hopefully somebody can explain why :)