Binding a Button in WPF MVVM

Scottintexas

Member
Joined
Jun 21, 2018
Messages
10
Location
Texas
Programming Experience
5-10
I want to add a button to a row in a ListView. The row is simply several <TextBlocks> as defined in a <DataTemplate> in a <ResouceDictionary>. The command is in the ViewModel. I am missing a "connection" to the command in the ViewModel. If I add the button right to the View I can easily bind it to the code. But separating it to the ResourceDictionary makes the command invisible.


XAML in MainWindowView:
   <Window.Resources>
        <ResourceDictionary Source="./ViewResources.xaml" />
    </Window.Resources>

    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>

    <ListView ItemsSource="{Binding Ports, Mode=OneWay}"
                                            ItemTemplate="{StaticResource ComportTemplate}"/>

ViewResources:
<DataTemplate x:Key="ComportTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Button Grid.Row="0"
                    Grid.Column="0"
                    Background="Red"
                    Height="10"
                    Width="10"
                    Margin="10"
                    VerticalAlignment="Center"
                    Command="{Binding TestPortCommand}"
                    CommandParameter="{Binding ElementName=PortName, Path=Text}"/>
                    
            <TextBlock x:Name="PortName"
                       Grid.Column="1"
                       VerticalAlignment="Center"
                       Margin="1,4,4,4">
            </TextBlock>
        </Grid>
    </DataTemplate>

Then in the MainWindowViewModel there is the code to handle the command.
MainWindowViewModel:
        private RelayCommand selectFilesCommand;
        private RelayCommand uploadCommand;
        private RelayCommand printFileCommand;
        private RelayCommand removeFileCommand;
        private RelayCommand testPortCommand;

        /// <summary>
        ///ICommand for the Select Files Button
        /// </summary>
        public ICommand SelectFilesCommand
        {
            get
            {
                if (selectFilesCommand == null)
                {
                    selectFilesCommand = new RelayCommand(param => SelectFiles());
                }
                return selectFilesCommand;
            }
        }

        /// <summary>
        /// Button to test communications with the serial port.
        /// </summary>
        /// <param name="port"></param>
        public ICommand TestPortCommand
        {
            get
            {
                if (testPortCommand == null)
                {
                    testPortCommand = new RelayCommand(param => TestComPort(param));
                }
                return testPortCommand;
            }
        }

A break point at the getter never gets hit. Unlike the SelectFilesCommand. That and the other buttons work great. But they are not being created in a DataTemplate.

Thanks for looking.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,469
Location
Chesapeake, VA
Programming Experience
10+
You are comparing to your SelectFilesCommand, but you don't seem to show us how you are binding to it.
 

Scottintexas

Member
Joined
Jun 21, 2018
Messages
10
Location
Texas
Programming Experience
5-10
The select files command binding is in the MainWindowView, not in the resource dictionary.

C#:
<Button Content="Select Saved Files"
    Width="100"
    Margin="0,5,2,5"
    Command="{Binding SelectFilesCommand}"/>

But the key thing is that it is in the MainWindowView. If I put the test button in the MainWindowView, it would work just fine. It would look stupid because it doesn't belong out there just hanging around. It belongs to a specific SerialPort. So I put it in the list with the serial ports.
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
5,469
Location
Chesapeake, VA
Programming Experience
10+
You'll need to move the TestPortCommand into the view model for the objects exposed by your Ports property. Recall that bindings are relative to the data context of the container. Since you are using a data template with the ListView, the bindings you use within that data template are relative to each object in the list. I know that WPF binding syntax lets you navigate down deeper, but I don't know if it was a way for you to navigate up and out of a container.
 
Top Bottom