Home > Software design >  WPF binding to UserControl from Page
WPF binding to UserControl from Page

Time:09-22

I have a UWP application, and it has a page containing a few textbox controls bound to A.B.C[2].D, A.B.C[2].E, A.B.C[2].F, and so on Now I want to move the text boxes to a separate UserControl to simplify my page's XAML but still want them to be bound to A.B.C[2].D, A.B.C[2].E etc. How can I achieve this?

Thank you

Here is my UserControl

<UserControl
    x:Class="Inspecto.HWStatusDisplayControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Truphase360"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="250">

    <Grid>
        <Grid.Resources>
            <Style x:Key="styleTxtBox" TargetType="TextBox">
                <Setter Property="IsReadOnly" Value="True" />
                <Setter Property="Width" Value="75"/>
            </Style>
            <Style x:Key="styleTxtBlk" TargetType="TextBlock">
                <Setter Property="FontSize" Value="12" />
                <Setter Property="Margin" Value="10"/>
                <Setter Property="Width" Value="75" />
            </Style>
        </Grid.Resources>
        <StackPanel Orientation="Vertical"  Margin="20">
            <TextBlock Text="{x:Bind Header}" FontSize="16" FontWeight="Bold" Margin="10">
            </TextBlock>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Temp1" Style="{StaticResource styleTxtBlk}" />
                <TextBox  Style="{StaticResource styleTxtBox}" Text="{Binding Mode=OneWay, Path=Temperature1 }" />
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Temp2" Style="{StaticResource styleTxtBlk}" />
                <TextBox  Style="{StaticResource styleTxtBox}" Text="{Binding Mode=OneWay, Path=Temperature2 }" />
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="SW Version" Style="{StaticResource styleTxtBlk}" />
                <TextBox Style="{StaticResource styleTxtBox}" Text="{Binding Mode=OneWay, Path=SWVersionStr }" />
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="HW Version" Style="{StaticResource styleTxtBlk}" />
                <TextBox Style="{StaticResource styleTxtBox}" Text="{Binding Mode=OneWay, Path=HWVersionStr }" />
            </StackPanel>
        </StackPanel>
    </Grid>
</UserControl>

The code block directly under exists inside a page and is repeated multiple times. The TextBoxs' were bound to {x:Bind ViewModel.DeviceData.Status.Devices[0].Temperature1 } and so on inside the Page Now I want to display the same from UserControl.

In the data object, the instance of Devices[] is replaced every few seconds. The new array was created by deserializing from JSON object and directly assigned to like ViewModel.DeviceData.Status.Devices = FromJSON(string);

Thank you

CodePudding user response:

I agree with @EldHasp. The solution for your scenario is that you might need to create a custom dependency property in the UserControl. Then pass the A.B.C object to this property of the UserControl via binding.

I've made a simple demo about this, you could take look at the code and adjust it for your scenario.

UserControl XAML

 <Grid x:Name="MyGrid">
    <Grid.Resources>
        <Style x:Key="styleTxtBox" TargetType="TextBox">
            <Setter Property="IsReadOnly" Value="True" />
            <Setter Property="Width" Value="75"/>
        </Style>
        <Style x:Key="styleTxtBlk" TargetType="TextBlock">
            <Setter Property="FontSize" Value="12" />
            <Setter Property="Margin" Value="10"/>
            <Setter Property="Width" Value="75" />
        </Style>
    </Grid.Resources>
    <StackPanel Orientation="Vertical"  Margin="20">
        <TextBlock Text="{x:Bind Header}" FontSize="16" FontWeight="Bold" Margin="10">
        </TextBlock>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Temp1" Style="{StaticResource styleTxtBlk}" />
            <TextBox  Style="{StaticResource styleTxtBox}" Text="{Binding MyDependencyProperty._List[0].Name}" />
        </StackPanel>
    </StackPanel>
</Grid>

UserControl Code

 public AClass MyDependencyProperty
    {
        get { return (AClass)GetValue(MyDependencyPropertyProperty); }
        set { SetValue(MyDependencyPropertyProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyDependencyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyDependencyPropertyProperty =
        DependencyProperty.Register("MyDependencyProperty", typeof(AClass), typeof(TestUserControl), new PropertyMetadata(null));

    public string Header = "TestHeader";

    public TestUserControl()
    {
        this.InitializeComponent();

        this.DataContext = this;
    }

MainPage Xaml

 <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Foreground="Red" Text="{x:Bind ViewModel._AClass._List[1].Name}"/>
    
    <local:TestUserControl Grid.Row="1" MyDependencyProperty="{x:Bind ViewModel._AClass}"/>
</Grid>

MainPage Code

 public sealed partial class MainPage : Page
{
    public TestViewModel ViewModel { get; set; }

    public MainPage()
    {
        this.InitializeComponent();
        ViewModel= new TestViewModel();
    }
}

public class TestViewModel 
{
    public AClass _AClass { get; set; }

    public TestViewModel()
    {
        _AClass = new AClass();
    }
}

public class AClass
{
    public List<BClass> _List { get; set; }

    public AClass()
    {
        _List = new List<BClass>();
        _List.Add(new BClass { Name = "123" });
        _List.Add(new BClass { Name = "234" });
    }
}

public class BClass
{
     public string Name { get; set; }
}

And the result: enter image description here

  • Related