Home > database >  How to access a public variable in a WPF Page from a UserControl?
How to access a public variable in a WPF Page from a UserControl?

Time:10-20

i have a WPF-Page that hosts a UserControl. The UserControl has a Button that does stuff and eventually wants to change the List that is bound to the DataGrid on the Page. Unfortunately I cannot access this List/DataGrid. It seems that the Page can access all public variables from the hosted UserControl but the UserControl cannot access any variable from the Page... Can anyone help me please?

here`s the xaml of my page:

<Page x:Class="SchrauberDB.View.Werkzeug_Window"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:SchrauberDB.Controls"
  xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
  Title="Werkzeug_Window"
  mc:Ignorable="d" 
  FontFamily="../Fonts/Poppins/#Poppins"

  d:DesignWidth="1400" d:DesignHeight="950"
  >

    <StackPanel
                Orientation="Horizontal"
                VerticalAlignment="Center"
                HorizontalAlignment="Right"
                Margin="0,0,0,0.2" Width="404"
                >

        <Button 
            Height="45" Width="150"  
            Margin="20,0,0,0"
            Background="{x:Null}" 
            Click="FilterMaske_Click"
            >

            <StackPanel Margin="0,0,0,0" HorizontalAlignment="Left" Width="90">

                <Image Height="30" Width="30" HorizontalAlignment="Left" Source="Assets\filter-outline_black.png" />
                <Label Content="Filter" HorizontalAlignment="Center" Margin="20,-30,0,0"  FontSize="14" Height="30"/>
            </StackPanel>
        </Button>

    </StackPanel>

    <DataGrid x:Name="DataGrid" 
              AlternatingRowBackground="#F8F8F8" Margin="40,60,40,45"
              Grid.Column="2" Grid.ColumnSpan="10"
              Grid.Row="1" Grid.RowSpan="12"
              RowHeight="47"
              ColumnHeaderHeight="47"
              Padding="0"
              FontSize="18"
              ColumnWidth="150"
              HorizontalScrollBarVisibility="Visible"
              AutoGenerateColumns ="False"
              >
        
        <DataGrid.Columns >
            <DataGridTextColumn x:Name="filter" Header="Filter" FontSize="18"   IsReadOnly="True" Binding="{Binding Path=filter}"></DataGridTextColumn>
            <DataGridTextColumn x:Name="bemiNr" Header="Bemi Nr" FontSize="18"   IsReadOnly="True" Binding="{Binding Path=bemiNr}"></DataGridTextColumn>
        </DataGrid.Columns>

    </DataGrid>

    <local:FilterWerkzeug x:Name="Filtermaske" Padding="10" Visibility="Collapsed"></local:FilterWerkzeug>
</Grid>

In the Code Behind of the Page i have a List that is bound to the DataGrid:

public List<DataModel.Werkzeug> werkzeuge = new List<DataModel.Werkzeug>();
//Some logic...
DataGrid.ItemsSource = werkzeuge;

In the Code Behind of the UserControl i have a Button that finally wants to update the List werkzeuge

Here´s the xaml of the UserControl:

<UserControl x:Class="SchrauberDB.Controls.FilterWerkzeug"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:SchrauberDB.Controls"
         mc:Ignorable="d" 
         d:DesignHeight="200" d:DesignWidth="1100"
         FontFamily="../Fonts/Poppins/#Poppins">

<Grid Background="#FEFFFF" >
    <StackPanel Grid.Row="0" Grid.Column="0">
        <TextBlock>filter</TextBlock>
        <ComboBox x:Name="cbFilter" Width="150"/>
    </StackPanel>

    <Button Height="45" Width="130" Margin="17.6,14.4,10,7" Click="Button_Click">
        <TextBlock  FontSize="14" FontWeight="Medium">
            Filter
        </TextBlock>
    </Button>
</Grid>
</UserControl>

CodePudding user response:

This is a really quick example:

  • page data context is a Model object with a public list
  • page shows that list
  • page shows a user control
  • this user control has a button
  • that button updates the list in the Model

enter image description here

The model:

using System.Collections.ObjectModel;

namespace WpfApp1
{
    public class Model
    {
        public ObservableCollection<string> Strings { get; } = new();
    }
}

The user control XAML:

<UserControl x:Class="WpfApp1.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:wpfApp1="clr-namespace:WpfApp1"
             mc:Ignorable="d"
             d:DataContext="{d:DesignInstance wpfApp1:Model}"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Button Content="Add" Click="ButtonBase_OnClick" />
    </Grid>
</UserControl>

The user control code:

using System;
using System.Windows;

namespace WpfApp1
{
    public partial class UserControl1
    {
        public UserControl1()
        {
            InitializeComponent();
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            var model = DataContext as Model ?? throw new InvalidOperationException();
            model.Strings.Add(DateTime.Now.ToString("O"));
        }
    }
}

The page XAML:

<Page x:Class="WpfApp1.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="clr-namespace:WpfApp1"
      mc:Ignorable="d"
      d:DesignHeight="450" d:DesignWidth="800"
      Title="Page1"
      d:DataContext="{d:DesignInstance local:Model}">

    <Page.DataContext>
        <local:Model />
    </Page.DataContext>

    <StackPanel>
        <local:UserControl1 />
        <ItemsControl ItemsSource="{Binding Strings}" />
    </StackPanel>

</Page>

The page code:

namespace WpfApp1
{
    public partial class Page1
    {
        public Page1()
        {
            InitializeComponent();
        }
    }
}

The window XAML:

<NavigationWindow x:Class="WpfApp1.MainWindow"
                  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                  mc:Ignorable="d"
                  Source="Page1.xaml">
</NavigationWindow>

The window code:

namespace WpfApp1
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

CodePudding user response:

Make your variable a property by adding {get; set;} after the variable name and before the assignment operator. WPF wants to access properties, not variables. You will also want to include and implement the INotifyPropertyChanged interface on your code behind class.

  • Related