unable to get a TextBlock Binding to connect to a backing Db Class Property in WPF

Ian turner 66 Reputation points
2021-07-29T11:06:29.757+00:00

I am using VS2019 to develop a program using the NorthWind Db, basically to learn/improve my C# skills. I am not an expert by any means although I have used "C" in various forms for a great many years

I have a window with multiple DataGrids, each bound to a different Db backing class, which bind just fine, and each has a header line with total records, current record etc above it.

My problem is that my XAML will NOT read the data from the background class, although debugging show it updating the values with the Setter as expected, but the getter is never called

To clarify the scenario, the current setup is :

XAML file :-

<!--Keys to access the background data classes-->

<local:Nwcustomer x:Key="CustDb"/>

<local:Nworder x:Key="OrderDb"/>

<local:Nworderdetails x:Key="OrderDetailsDb"/>

<local:Nwcategory x:Key="CategoryDb"/>

The above have no errors at all on them, so are presumably correct..
It is the Nwcustomer class that has the CustomerCurrent property that is giving me the problem.

The offending control is :

<TextBlock x:Name="CustCurrent"  
            DataContext="{StaticResource CustDb}"
            Text="{Binding CustomerCurrent, diag:PresentationTraceSources.TraceLevel=High, UpdateSourceTrigger=PropertyChanged }"
            Height="25"
            FontWeight="Bold"
            Padding="3"
            VerticalAlignment="Center"
            Background="Transparent"
            Width="30"                   
            Foreground="{StaticResource Black1}"/>

There are no apparent errors in the above, and hovering over the CustomerCurrent shows it identified as an int32, which is correct

I have even tried removing the Propertychanged from the binding. Still no change in operation.

When debugging the App The CustomersCurrent Property Setter is triggered by the line :

nwcustomer . CustomerCurrent = CustomersGrid . SelectedIndex; in the Cs file

and if I use CustomerCurrent to set the .Text field after the values are set in the CS file, it works correctly, and the GETTER is called as expected.

It is just that the TextBlock will NOT do it in XAML, although filling the TextBox field in Code Behind works perfectly.

I have tried it in another similar but separate window with the same non result.
This is driving me crazy, I have a couple of other similar fields, all are having the same issue.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,686 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Hui Liu-MSFT 41,261 Reputation points Microsoft Vendor
    2021-08-06T08:38:40.82+00:00

    How do you bind the data of the database table to the DataGrid? If I am not misunderstood, you want to bind the selected index to the TextBlock. I use the following code to display the selected index in the TextBlock. And getter can get the changed value. Could you try to use the following code in your project. If I misunderstood, please let me know.
    The code of MainWindow. Xaml:

    <StackPanel >  
            <DataGrid Name="dataGrid" SelectedCellsChanged="dataGrid_SelectedCellsChanged"   AutoGenerateColumns="False" Height="380">  
                <DataGrid.Columns>  
                    <DataGridTextColumn Header="CustomerID" Width="80" Binding="{Binding CustomerID}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="CompanyName" Width="100" Binding="{Binding CompanyName}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="ContactName" Width="90" Binding="{Binding ContactName}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="ContactTitle" Width="80" Binding="{Binding ContactTitle}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Address" Width="100" Binding="{Binding Address}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="City" Width="50" Binding="{Binding City}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Region" Width="50" Binding="{Binding Region}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="PostalCode" Width="80" Binding="{Binding PostalCode}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Country" Width="100" Binding="{Binding Country}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Phone" Width="80" Binding="{Binding Phone}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Fax" Width="80" Binding="{Binding Fax}"></DataGridTextColumn>  
                </DataGrid.Columns>  
            </DataGrid>  
            <TextBlock Width="1000" Height="50" Name="tb" Text="{Binding Source=CustomerCurrent}"/>  
            <TextBlock  Width="1000" Height="100" Name="myTxt" TextWrapping="Wrap" Background="AliceBlue" HorizontalAlignment="Left"></TextBlock>  
        </StackPanel>  
    

    The code of MainWindow. Xaml.cs:

    public partial class MainWindow : Window,INotifyPropertyChanged  
      {  
        public MainWindow()  
        {  
          InitializeComponent();  
          FillGrid();  
        }  
        private void FillGrid()  
        {  
          string constr = @"constr ";  
          SqlConnection con = new SqlConnection(constr);  
          con.Open();  
          SqlCommand cmd = new SqlCommand("Select * From [dbo].[Customers]", con);  
          SqlDataAdapter da = new SqlDataAdapter(cmd);  
          var dt = new DataTable();  
          da.Fill(dt);  
          dataGrid.ItemsSource = dt.DefaultView;  
          con.Close();  
        }  
        private int customerCurrent;   
        public int CustomerCurrent  
        {  
          get  
          {  
            return customerCurrent;  
          }  
          set  
          {  
            customerCurrent = value;  
            OnPropertyChange("CustomerCurrent");  
          }  
       }  
        public event PropertyChangedEventHandler PropertyChanged;  
        protected void OnPropertyChange(string propertyName)  
        {  
          PropertyChangedEventHandler handler = this.PropertyChanged;  
          if (handler != null)  
          {  
            var e = new PropertyChangedEventArgs(propertyName);  
            handler(this, e);  
           }     
    }  
        private void dataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)  
        {  
          int select= dataGrid.SelectedIndex;  
          customerCurrent = select;  
          tb.Text = customerCurrent.ToString();   
        }   
      }  
    

    The result picture:
    121050-6.gif

    Update:

    Your CustomerCurrent is actually binding the SelectedIndex of the DataGrid to the Textblock. You could bind SelectedIndex directly in xaml. The code here is used to bind TextBlock directly to SelectedIndex.

    The code of MainWindow. Xaml:

    <StackPanel >  
            <DataGrid Name="dataGrid"    AutoGenerateColumns="False" Height="380">  
                <DataGrid.Columns>  
                    <DataGridTextColumn Header="CustomerID" Width="80" Binding="{Binding CustomerID}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="CompanyName" Width="100" Binding="{Binding CompanyName}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="ContactName" Width="90" Binding="{Binding ContactName}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="ContactTitle" Width="80" Binding="{Binding ContactTitle}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Address" Width="100" Binding="{Binding Address}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="City" Width="50" Binding="{Binding City}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Region" Width="50" Binding="{Binding Region}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="PostalCode" Width="80" Binding="{Binding PostalCode}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Country" Width="100" Binding="{Binding Country}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Phone" Width="80" Binding="{Binding Phone}"></DataGridTextColumn>  
                    <DataGridTextColumn Header="Fax" Width="80" Binding="{Binding Fax}"></DataGridTextColumn>  
                </DataGrid.Columns>  
            </DataGrid>  
            <TextBlock Width="1000" Height="50" Name="tb"  Background="AliceBlue" HorizontalAlignment="Left" Text="{Binding SelectedIndex, ElementName=dataGrid}" />  
        </StackPanel>  
    

    The code of MainWindow. Xaml.cs:

    public partial class MainWindow : Window,INotifyPropertyChanged  
      {  
        public MainWindow()  
        {  
          InitializeComponent();  
           
          FillGrid();  
        }  
        private void FillGrid()  
        {  
          string constr = @"constr ";  
          SqlConnection con = new SqlConnection(constr);  
          con.Open();  
          SqlCommand cmd = new SqlCommand("Select * From [dbo].[Customers]", con);  
          SqlDataAdapter da = new SqlDataAdapter(cmd);  
          var dt = new DataTable();  
          da.Fill(dt);  
          dataGrid.ItemsSource = dt.DefaultView;  
          List<int> SelectedIndexs = dataGrid.SelectedItems  
            .Cast<DataRowView>()  
            .Select(view => dt.Rows.IndexOf(view.Row))  
            .ToList();  
          con.Close();  
        }  
      
        public event PropertyChangedEventHandler PropertyChanged;  
        protected void OnPropertyChange(string propertyName)  
        {  
          PropertyChangedEventHandler handler = this.PropertyChanged;  
          if (handler != null)  
          {  
            var e = new PropertyChangedEventArgs(propertyName);  
            handler(this, e);  
          }  
        }  
      }   
    

    The result picture:
    122613-6.gif

    0 comments No comments

  2. Ian turner 66 Reputation points
    2021-08-06T09:45:38.17+00:00

    Thanks for that response, but you have actually sidestepped, or missed the major problem !
    You use the line :

    tb.Text = customerCurrent.ToString();

    in code behind to set the text field, which I could do already. My problem is that I do NOT want to do it in c# code, I want the binding in XAML to handle it automatically?

    Does that make sense ?