These are chat archives for AvaloniaUI/Avalonia

2nd
Jan 2019
Benedikt Schroeder
@Gillibald
Jan 02 01:17
Are you using the current master(nightly builds)? Otherwise you have to use the resm scheme.
ksigne
@ksigne
Jan 02 10:03
I have a question directly to @grokys
If you use ! operator to initiate a binding
How you're supposed to break it/
?
Wiesław Šoltés
@wieslawsoltes
Jan 02 11:04
Try setting to AvaloniaProperty.UnsetValue or null ?
ksigne
@ksigne
Jan 02 11:10
this doesn't kill binding
ksigne
@ksigne
Jan 02 12:19
and what's the idea of having more than one binding set per single binding level
ksigne
@ksigne
Jan 02 12:31
so you can make two bindings through ! operator, so both of them will work in sense that value will change on incoming event
Wiesław Šoltés
@wieslawsoltes
Jan 02 12:41
I think bondings implement IDisposable
ksigne
@ksigne
Jan 02 12:50
they don't!
personally I still don't understand the design with putting more than one observer into single AvaloniaProperty+Priority
ahopper
@ahopper
Jan 02 13:29
a fun weekend project for someone to port to Avalonia http://musicengravingcontrols.com/ :)
Steven Kirk
@grokys
Jan 02 14:17
@ksigne yeah good point - there is no way to break a binding with the ! operator other than having the bound observable complete
if you want to be able to break it, use Bind
multiple bindings per binding level are used by styles
Jonathan
@vanillajonathan
Jan 02 14:23
<Line Stroke="Green" StartPoint="0,100" EndPoint="200,100" StrokeThickness="2" RenderTransformOrigin="0.5,0.5">
  <Line.RenderTransform>
    <RotateTransform Angle="{Binding MyControl.Rotation}" />
  </Line.RenderTransform>
</Line>
This code rotates the line from the start instead of the center or something. I want it to rotate from the center and stay in the center.
ksigne
@ksigne
Jan 02 14:27
@grokys how exactly they are used? why can't you just rewrite binding instead of keeping them
actually it looks like object leak
i'm trying to analyze sources to write educational article... and I understand DependencyProperty design less and less...
ksigne
@ksigne
Jan 02 14:33
also what is obviously different from WPF is that copy of value is seems to be copied into each instance of AvaloniaObject inside ValueStore
while in WPF it is kept in single HashDictionary
so memory consumption is going to be far larger...
on complex logical trees
you can see there are >1 styles that apply to each button
ksigne
@ksigne
Jan 02 14:38
@vanillajonathan RotateTransform is missing CenterX and CenterY, so you TransformGroup with two TranslateTransform and single RotateTransform
Steven Kirk
@grokys
Jan 02 14:38
also you can override a button's styles locally, e.g. you can have the default button style in the App.xaml and another style in the window
ksigne
@ksigne
Jan 02 14:38
ok, you can, but there is still one actual binding per property
Steven Kirk
@grokys
Jan 02 14:38
yes there is only a single active binding per property
ksigne
@ksigne
Jan 02 14:39
that's what I say
you can have more than one active binding per property
and they will work as "last coming" rule
Steven Kirk
@grokys
Jan 02 14:39
yes exactly
ksigne
@ksigne
Jan 02 14:39
so it keeps to IObservable and react to both events
which is obviously wrong behavior and binding leak
it should keep only one
e.g. you can bind to two objects simultaneously and get value of object updated last
Steven Kirk
@grokys
Jan 02 14:40
problem is that you don't know if a binding is going to produce UnsetValue
there are certain styles, e.g. Button that will never produce UnsetValue so there we could actually short-circuit
Jonathan
@vanillajonathan
Jan 02 14:41
@ksigne Oh that sounds tricky. I wouldn't know how to do that.
Steven Kirk
@grokys
Jan 02 14:41
but the property system isn't aware of that
ksigne
@ksigne
Jan 02 14:41
so that's why in WPF Style are separate bindingpriority
wpf have 9 priorities while you have only 6
so my opinion that you should have only one binding per prioirity
if you bind you rewrite existing one
if you bind to null to remove
Steven Kirk
@grokys
Jan 02 14:43
how would Button:pointerover work in that case?
Button:pointerover needs to fall back to Button when the pointer is not over the button
ksigne
@ksigne
Jan 02 14:44
you already have separate priority for style triggers
so when style is revoked, you put Unset to that priority
Steven Kirk
@grokys
Jan 02 14:44
ok, lets say Button:pointerover and Button:pressed
they're both style trigger priority
ksigne
@ksigne
Jan 02 14:45
last one is applied..
so you basically put :pressed afterwards :pointover in style file
Steven Kirk
@grokys
Jan 02 14:45
but then :pressed would overwrite :pointerover?
ksigne
@ksigne
Jan 02 14:46
why?
properties are treated separately
Steven Kirk
@grokys
Jan 02 14:46
because you say "you should only have one binding per priority"
ksigne
@ksigne
Jan 02 14:46
yes, on each property separately
when :pressed is gone you have to reassign
Steven Kirk
@grokys
Jan 02 14:47
right, and what if :pressed and :pointerover both affect Background?
ksigne
@ksigne
Jan 02 14:47
the latter applied
which is the latter in stylefile
Steven Kirk
@grokys
Jan 02 14:47
i think i'm having a problem understanding ;)
Jonathan
@vanillajonathan
Jan 02 14:47
Why doesn't RotateTransform have CenterX and CenterY?
ksigne
@ksigne
Jan 02 14:47
because some1 forgot to add it
if you want I can add
put you will make PR, i'm not convenient with github
Steven Kirk
@grokys
Jan 02 14:48
@vanillajonathan there's RenderTransformOrigin on Visual
ksigne
@ksigne
Jan 02 14:49
@grokys in wpf it has centerx and centery...
as well as RenderTransformOrigin
Steven Kirk
@grokys
Jan 02 14:49
ah yeah so it does
Jonathan
@vanillajonathan
Jan 02 14:49
@grokys Yes, and I've set that to RenderTransformOrigin="0.5,0.5" but doesn't seem to work.
Steven Kirk
@grokys
Jan 02 14:50
sounds like that should be added then
@vanillajonathan try setting it to 50%,50%
ksigne
@ksigne
Jan 02 14:50
@grokys imagine you have Button:pointerover {Background: yellow} and Button:pressed {Background: blue}
so when observer see pointerover it fires binding update
and then it see :pressed it fires binding update once again
so final value is "blue"
Jonathan
@vanillajonathan
Jan 02 14:51
@grokys Thanks. Oddly enough, that helped. Why did 50%,50% work, but 0.5,0.5 not work?
Steven Kirk
@grokys
Jan 02 14:51
because 0.5,0.5 is a pixel position, whereas 50%,50% is a relative position
WPF only had relative positions, which caused me lots of pain
@ksigne what do you mean by "it fires binding update"?
ksigne
@ksigne
Jan 02 14:54
it rewrites binding of particular priority..
Steven Kirk
@grokys
Jan 02 14:54
ok, and when the button is no longer pressed, it removes the binding?
ksigne
@ksigne
Jan 02 14:54
it rewrites back again
Steven Kirk
@grokys
Jan 02 14:55
rewrites what back again?
ksigne
@ksigne
Jan 02 14:56
last style that matches
so you idea is to keep all styles as separate bindings
Steven Kirk
@grokys
Jan 02 14:56
ok, so each time a style is deactivated, it re-traverses the tree for the next binding that is active?
ksigne
@ksigne
Jan 02 14:57
yeah. probably you can pre-cache styles that matches particular object without additional conditions
current impl doesn't allow even detaching styles
Steven Kirk
@grokys
Jan 02 14:57
ok, i think i understand now
yeah, detaching styles isn't yet implemented
ksigne
@ksigne
Jan 02 14:58
you can't do that with current design... you leak bindinginstance...
Steven Kirk
@grokys
Jan 02 14:58
you can do it
ksigne
@ksigne
Jan 02 14:58
how?
Steven Kirk
@grokys
Jan 02 14:59
we could either store an IDisposable for each binding, or make the binding complete when the style is removed
i did consider re-traversing the tree when a style is activated/deactivated
however it looked like it would be a lot slower
and "pre-caching styles that match particular object" is exactly what lead to the current design
ksigne
@ksigne
Jan 02 15:00
yeah, but it leads to leaks..
Steven Kirk
@grokys
Jan 02 15:02
do you mean the observables are not being cleaned up when a control is removed from the tree?
ksigne
@ksigne
Jan 02 15:02
i'm not sure about that yet - I didn't analyzed .Controls yet, only .Base
but when you bind manually you end up with IDisposable or nothing
Steven Kirk
@grokys
Jan 02 15:03
ok, bindings from styles should be cleaned up
ksigne
@ksigne
Jan 02 15:03
and there is no way to track which observer leads to which object in runtime
and there is no way to clean them from code-behind
Steven Kirk
@grokys
Jan 02 15:05
maybe if i could see some code i could understand better
if you use .Bind you get an IDisposable which can stop the binding
ksigne
@ksigne
Jan 02 15:06
so from user prospective you only have IBinding
Steven Kirk
@grokys
Jan 02 15:06
but you don't want to call Dispose on the IDisposable is that right?
ksigne
@ksigne
Jan 02 15:07
when do you want to call it?
Steven Kirk
@grokys
Jan 02 15:07
when you want to destroy the binding
ksigne
@ksigne
Jan 02 15:07
e.g. you initiate binding from some local context... you have anyway to put it into some global cache or whatever
and the clean it up when it doesn't make sense anymore
Steven Kirk
@grokys
Jan 02 15:07
yes, you will have to do that
how would you like to do it?
when should the bindings be destroyed?
ksigne
@ksigne
Jan 02 15:08
but why can't we keep them inside AvaloniaObject they are bound to?
I mean that current design is very sparse. You have lots of objects that doing almost same but they are not coupled, and you cannot track from one to another..
Steven Kirk
@grokys
Jan 02 15:09
i think i might be starting to understand... instead of keeping track of the bindings, you want a way to say "destroy all bindings for this property on this object`?
ksigne
@ksigne
Jan 02 15:10
Ideally if you can track which binding is which
Or you limit number of bindings e.g. 1 per priority level
So they can be removed or rewritten without unintended side effects
Steven Kirk
@grokys
Jan 02 15:10
could you give me a code example of how you would like to dispose bindings?
ksigne
@ksigne
Jan 02 15:11
object[!property] = null
obviously
Steven Kirk
@grokys
Jan 02 15:12
and if that property has bindings from a style applied, what would it do?
ksigne
@ksigne
Jan 02 15:12
!property is localvalue...
Steven Kirk
@grokys
Jan 02 15:12
do you just want to dispose the local priority binding?
ah ok
it might make sense to have a method which can do that
ksigne
@ksigne
Jan 02 15:12
i would rather limit local priority to just one binding
so existing will be broken
Steven Kirk
@grokys
Jan 02 15:13
WPF has BindingOperations.ClearBinding
ksigne
@ksigne
Jan 02 15:13
WPF doesn't have multiple binding in this sense
Steven Kirk
@grokys
Jan 02 15:13
but we do!
ksigne
@ksigne
Jan 02 15:13
so you can e.g. get bindingexpression back
e.g. you can get object[!property] but it is useless..
you cannot even convert it back to IObservable
Steven Kirk
@grokys
Jan 02 15:15
basically it sounds like you just want a completely different binding architecture
ours was based on observables
once you bind an observable in rx, there's not generally a way to "get it back"
ksigne
@ksigne
Jan 02 15:17
you can at least get IObservable back..
Steven Kirk
@grokys
Jan 02 15:18
if i do var bar = obs.Select(x => x.Foo) and then don't keep a reference to obs there's no way to get a reference to it back from bar
ksigne
@ksigne
Jan 02 15:19
yes that's true, but you still keep reference to final observable, so it is actual pipe you're binding to
so you can reuse it, analyze it or detach it
about styles: what if you use composite subject which acts like multibinding..
Steven Kirk
@grokys
Jan 02 15:20
i think i'm missing some context in that i can't really understand your problem on a concrete level, if i could see some code that you were having a problem with i might be able to understand
ksigne
@ksigne
Jan 02 15:21
root generally is experimenting with IndexerDescriptor
so what I've expecting is when you do
object[!property] = observable.ToBinding()
you set binding
if you do object[!property].Observable you can get it
and if you do object[!property]?.Die() you destroy binding
and if you do object[!property] = anotherObservable.ToBinding() first one does not work anymore
Steven Kirk
@grokys
Jan 02 15:23
ok, so the problem just that things don't work how you expect
that's fair enough
but without a concrete example of something you can't do
ksigne
@ksigne
Jan 02 15:23
yeah, and i don't really understand why they are working another way :d
Steven Kirk
@grokys
Jan 02 15:23
it'd be a lot of work to completely change our binding system
so basically you're just saying "i don't like it"
again fair enough
but i'm afraid that's how it is
ksigne
@ksigne
Jan 02 15:24
i would rather say i want to understand underlying intentions..
Steven Kirk
@grokys
Jan 02 15:25
underlying intentions were i guess:
ksigne
@ksigne
Jan 02 15:25
if it was a specific design or just a shortcut
multiple bindings is ok with styles when values doesn't change; for others it produce weird side-effect
Steven Kirk
@grokys
Jan 02 15:26
  1. based on rx
  2. multiple styles can apply to a single property
  3. style triggers can turn on and off
  4. specific binding levels don't have any particular logic, they're just numbers
i think your problem is probably with 4
you think that local binding priority should function differently to style trigger priority
i seem to remember things were more like that at some point
but then we simplified it to make all binding priorities work the same
ksigne
@ksigne
Jan 02 15:28
let's try imagine following (let's keep XAML Binding out of scope now)
you have objects incoming asynchronously time to time... and when they come you binding your UI to them
so you have some callback and calling .Bind()
so currently you have to keep IDisposable somewhere in outer scope and Dispose() it is it is not null, and then bind once again
but that generally devaluates [!property] feature...
Steven Kirk
@grokys
Jan 02 15:30
yeah
ksigne
@ksigne
Jan 02 15:31
so if you can just [!property] = newobservable it would be much more elegant
Steven Kirk
@grokys
Jan 02 15:31
a few things about that: usually i'd put the logic in a view model so the logic is testable
and you'd bind to the view model
ksigne
@ksigne
Jan 02 15:32
so view is expected to be immutable as object..
Steven Kirk
@grokys
Jan 02 15:32
so assuming you're using MVVM these sort of bindings are limited lookless controls and very specific views
i wouldn't say immutable, no, but these sort of things are very rare in my experience
and in the rare case that i need this sort of feature, storing a disposable isn't a big deal
ksigne
@ksigne
Jan 02 15:33
yeah, i understand that i can solve my problems :d
Steven Kirk
@grokys
Jan 02 15:33
so then we're left with the [!property] syntax
this was added as a shortcut for declaring objects using the initializer syntax:
ksigne
@ksigne
Jan 02 15:34
as i said before i'm trying to write some texts about how Avalonia works inside, and how it can be used
so i end up with thoughts what is not perfect IMO in very core design
Steven Kirk
@grokys
Jan 02 15:34
var btn = new Button
{
   [!Grid.ColumnProperty] = new Binding("Foo")
}
the [!property] syntax there was added so you can do that ^^
ksigne
@ksigne
Jan 02 15:35
yeah, that makes sense, but still looks unfinished, so you can't remove or rewrite it
also as a suggestion
Steven Kirk
@grokys
Jan 02 15:36
but 99% of the time you don't want to remove or rewrite it
in that 1% case just use Bind and get a disposable
ksigne
@ksigne
Jan 02 15:36
you can also write !Grid.ColumnProperty+BindingPriority.Style
instead of separate ~ for this case
Steven Kirk
@grokys
Jan 02 15:36
yeah i keep meaning to remove ~
!Grid.ColumnProperty+BindingPriority.Style would be a good syntax!
ksigne
@ksigne
Jan 02 15:38
so what my feeling is that you can keep single binding for priority
and then bind +Style to composer which contains other bindings
that will make it still generalized but more adequate for LocalValue
Steven Kirk
@grokys
Jan 02 15:38
if you want to implement that and submit a PR, feel free ;)
ksigne
@ksigne
Jan 02 15:38
where multiple bindings simply doesn't make sense
Steven Kirk
@grokys
Jan 02 15:39
honestly though, i don't have time or the will to do that
ksigne
@ksigne
Jan 02 15:39
okay
i would implement that for myself locally, and then we can discuss once again
Steven Kirk
@grokys
Jan 02 15:40
yeah, give it a try, either you will understand the design better or i will understand that i designed it badly ;)
one part that we haven't implemented yet: AvaloniaUI/Avalonia#1883
ksigne
@ksigne
Jan 02 15:45
btw why won't you support custom uri as attribute on AvaloniaXamlLoader?
is there a reason?
Steven Kirk
@grokys
Jan 02 15:46
you mean an attribute with the URL on the class?
no reason, just no-one thought of it
what is the use-case?
ksigne
@ksigne
Jan 02 15:47
naming conventions, keeping xmls and classes in separate folders
just get rid of xaml extensions on files
Steven Kirk
@grokys
Jan 02 15:49
why do you want to do that?
ksigne
@ksigne
Jan 02 15:49
you mean extension?
Steven Kirk
@grokys
Jan 02 15:49
yeah
ksigne
@ksigne
Jan 02 15:49
it doesn't work well with vanilla xaml editor in VS and R#
missing namespaces, attached properties etc.
Steven Kirk
@grokys
Jan 02 15:50
we also support .paml extension if that's causing problems
ksigne
@ksigne
Jan 02 15:51
i'd like to keep it just xml so syntax highlight and folding still works e.g. in Rider
so i think having XamlUri attribute over class is still best solution ;)
Steven Kirk
@grokys
Jan 02 15:52
yeah that would work
oh hold on, no you can't sorry
might be worth us adding an overload which takes a URL then too
Luis von der Eltz
@toytonics
Jan 02 16:21
is there a way to provide a test view model for the visual studio extension? so that I can preview binding content?
ksigne
@ksigne
Jan 02 18:00
@grokys what I've done minimally to keep behavior I want and working styles, I enforced styles to be bound not to BindingPriority.Style but BindingPriority.Style+delta where delta is incrementing
that's not a good design overall but at least some point discuess
Jeremy Koritzinsky
@jkoritzinsky
Jan 02 18:41
@ksigne FYI I've been planning on implementing a CSS selector specificity feature in our styling (where a more specific selector always overrides a less specific one). Do you think there's a way your feature could coexist with that?
ksigne
@ksigne
Jan 02 18:51
I can't answer as I'm not that familiar with styling system yet and I can't see your implementation
ksigne
@ksigne
Jan 02 19:29
strange piece of code in ValueStore.cs
``` if (_values.TryGetValue(property, out var v))
{
priorityValue = v as PriorityValue;
            if (priorityValue == null)
            {
                if (priority == (int)BindingPriority.LocalValue)
                {
                    _values[property] = Validate(property, value);
                    Changed(property, priority, v, value);
                    return;
                }
                else
                {
                    priorityValue = CreatePriorityValue(property);
                    priorityValue.SetValue(v, (int)BindingPriority.LocalValue);
                    _values[property] = priorityValue;
                }
            }
        }```
In which case priorityValue can be null?
ah, it put object directly if there's only LocalValue inside
ksigne
@ksigne
Jan 02 19:35
but what if we have this local value, and then add value that has lower priority...
it seems that we ignore it totally
ok, got it finally
why you decide not to validate values that has non-local priorities?
just because they don't change? what about animations?
Jeremy Koritzinsky
@jkoritzinsky
Jan 02 19:41
I think validation happens in one of the Priority* classes in those cases
ksigne
@ksigne
Jan 02 20:16
yeah, I found that
ksigne
@ksigne
Jan 02 20:32
how validation function works?
it actually looks like coercion from WPF
but in some controls you drop exceptions straight from there...
ksigne
@ksigne
Jan 02 20:37
so ok, you'll get exception on setvalue
but how it will be converted to BindingNotification?