Re: Working with components / ECS?
This is where I've gotten up to and am trying out in C++, with hand-written "*ComponentName*Model" classes rather than the original components as struct properties or anything like that. An example of one of the optional health bars:
I've tried a few combinations; like setting template to x:Null or setting IsEnabled to False and Visibility to Hidden. The end result is always the same - that the 'IsLessThanPercentageConverter' used here is still being called, and with 'UnsetValue' types since the component doesn't exist. I was hoping the entire style and its bindings would cease to be processed. The above in use in my control xaml:
I've started messing with it in C++, and getting errors like
Which don't surprise me - I guess it's the aforementioned issues of still trying to access components that don't exist?
Code: Select all
<ControlTemplate x:Key="EmptyTemplate"></ControlTemplate>
<sys:Single x:Key="IntegrityLowPercent">0.25</sys:Single>
<Style x:Key="IntegrityBarAnimStyle" TargetType="ProgressBar" BasedOn="{StaticResource {x:Type ProgressBar}}">
<Style.Triggers>
<DataTrigger Binding="{Binding [HealthComponent], Converter={StaticResource IsNullConverter}}" Value="True">
<Setter Property="Template" Value="{StaticResource EmptyTemplate}"></Setter>
</DataTrigger>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource IsLessThanPercentageConverter}" Mode="OneWay">
<Binding Path="[HealthComponent].Integrity"/>
<Binding Path="[HealthComponent].MaxIntegrity"/>
<Binding Source="{StaticResource IntegrityLowPercent}"></Binding>
</MultiBinding>
</DataTrigger.Binding>
<DataTrigger.EnterActions>
<BeginStoryboard Name="LowIntegrityFlash">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Foreground.Color" To="{StaticResource IntegrityLowColor}" AutoReverse="True" Duration="0:0:0.1" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="LowIntegrityFlash"></StopStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
Code: Select all
<ProgressBar x:Name="IntegrityBar" Style="{StaticResource IntegrityBarAnimStyle}" RenderTransformOrigin="0.5,0.5" VerticalAlignment="Center" Panel.ZIndex="2" Margin="29,0,-29,0" Background="#FF575757" Height="5" Foreground="#FFD4D4D4" Value="{Binding [HealthComponent].Integrity, Mode=OneWay}" BorderBrush="#FFD4D4D4" Maximum="{Binding [HealthComponent].MaxIntegrity, Mode=OneWay}">
<ProgressBar.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="270"/>
<TranslateTransform/>
</TransformGroup>
</ProgressBar.RenderTransform>
</ProgressBar>
Code: Select all
[ 11/27/21 03:05:54 ] [warn] [RTG] Index 4294967295 out of bounds accessing EntityComponentsViewModel
[ 11/27/21 03:05:54 ] [error] [RTG] Binding failed: Path=[ShieldComponent].MaxShield, Source=EntityComponentsViewModel(''), Target=ProgressBar('ShieldBar'), TargetProperty=RangeBase.Maximum
[ 11/27/21 03:05:54 ] [warn] [RTG] Index 4294967295 out of bounds accessing EntityComponentsViewModel
[ 11/27/21 03:05:54 ] [error] [RTG] Binding failed: Path=[ShieldComponent].Shield, Source=EntityComponentsViewModel(''), Target=ProgressBar('ShieldBar'), TargetProperty=RangeBase.Value
-
sfernandez
Site Admin
- Posts: 2984
- Joined:
Re: Working with components / ECS?
Yes, that is correct, the DataTrigger needs to evaluate the binding to determine if it has to apply the setters or execute the specified actions. And even if part of the binding is null it calls the converter because some converters may accept a null as a valid value.the 'IsLessThanPercentageConverter' used here is still being called, and with 'UnsetValue' types since the component doesn't exist.
On a side note, you can simplify the first DataTrigger by comparing directly to {x:Null}
Code: Select all
<DataTrigger Binding="{Binding [HealthComponent]}" Value="{x:Null}">
<Setter Property="Template" Value="{StaticResource EmptyTemplate}"/>
</DataTrigger>
Those bindings shouldn't report an error message, this was a deviation from WPF, we've fixed that for the next release: #2200I've started messing with it in C++, and getting errors like
Anyway, if you want to avoid evaluating those bindings at all you can have an indirection. Instead of directly including the ProgressBar, you can have a Control that only sets its template when the component is available:
Code: Select all
<ControlTemplate x:Key="EmptyTemplate"/>
<ControlTemplate x:Key="ProgressBarTemplate">
<ProgressBar Style="{StaticResource IntegrityBarAnimStyle}" .../>
</ControlTemplate>
<Style x:Key="HealthControl" TargetType="Control">
<Setter Property="Template" Value="{StaticResource ProgressBarTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding [HealthComponent]}" Value="{x:Null}">
<Setter Property="Template" Value="{StaticResource EmptyTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
Code: Select all
<Control Style="{StaticResource HealthControl}"/>
Who is online
Users browsing this forum: No registered users and 90 guests