简体   繁体   中英

Binding Xaml UserControl view to it's code behind, but code behind bound to other object

I have a UserControl defined by Xaml and code behind. It should update as the model on which it is based changes.

I have constructed each instance of these controls in code, and set up bindings to some object _interestingSystem .

var newViewInstance = new BroadcastCell
{
    HeartbeatStatus = Heartbeat.Status.NotRx,
    BindingContext = _interestingSystem,
};
broadcastCell.SetBinding(BroadcastCell.HeartbeatProperty, "HeartbeatStatus");
StatkStack.Children.Add(broadcastCell);

These bindings work, and I can see the code-behind responding to the model changes just fine.

Now I want to bind my view to the code-behind after a little modification and adjustment.
XAML

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="56" />
        <RowDefinition Height="20" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="65" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>

    <Label Text="{Binding Title, FallbackValue=TestTitle, Mode=OneWay}" Grid.Column="1"  />
    <Label Text="{Binding SecondaryLine, FallbackValue=Test2nd}" Grid.Column="1" Grid.Row="1"  />
</Grid>

Code-behind

public Heartbeat.Status CurrentStatus;

static void OnHeartbeatStatusChanged(BindableObject sender, object oldValue, object newValue)
{
    var thisInstance = (BroadcastCell)sender;
    var newStatus = (Heartbeat.Status)newValue;
    thisInstance.CurrentStatus= newStatus;
}

private void UpdateAndModifyResult()
{
    SecondaryLine = $"{DateTime.Now} {CurrentStatus} @ {AnotherStatus}";
}

public String SecondaryLine
{
    get { return _secondaryLine; }
    set
    {
        _secondaryLine = value;
        OnPropertyChanged();
    }
}

Can I set the binding of the Xaml to the code-behind, and the code behind to another object as I am trying?
Or do I need to hard-code in the xaml property name into the code-behind to update them 'manually'?

In XAML, you can set the source of a Binding to the root BroadcastCell by using the FindAncestor binding mode like this:

<Label Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:BroadcastCell}}, Path=SecondaryLine}" Grid.Column="1" Grid.Row="1"/>

When loading the XAML, the binding engine will look up the visual tree for the first BroadcastCell object and bind to its SecondaryLine property.

Alternatively, you could directly bind your view to your model without the need to manually set any kind of binding in your code-behind by doing this:

<Label Text="{Binding Heartbeat.Status}" Grid.Column="1" Grid.Row="1"/>

provided that you set the DataContext of your view to the correct source object. Your code-behind would become:

broadcastCell.DataContext = _interestingSystem;

This is more appropriate than defining a binding in the code-behind.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM