Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Text initialization and updating for TokenizingTextBox #4786

Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ private static void TextPropertyChanged(DependencyObject d, DependencyPropertyCh
if (d is TokenizingTextBox ttb && ttb._currentTextEdit != null)
{
ttb._currentTextEdit.Text = e.NewValue as string;

// Notify inner container of text change, see issue #4749
var item = ttb.ContainerFromItem(ttb._currentTextEdit) as TokenizingTextBoxItem;
item?.UpdateText(ttb._currentTextEdit.Text);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ private void ItemsSource_PropertyChanged(DependencyObject sender, DependencyProp
}
}

_currentTextEdit = _lastTextEdit = new PretokenStringContainer(true);
// Add our text box at the end of items and set its default value to our initial text, fix for #4749
_currentTextEdit = _lastTextEdit = new PretokenStringContainer(true) { Text = Text };
_innerItemsSource.Insert(_innerItemsSource.Count, _currentTextEdit);
ItemsSource = _innerItemsSource;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using Windows.Foundation;
using Windows.System;
using Windows.UI;
Expand Down Expand Up @@ -100,29 +101,36 @@ private void OnApplyTemplateAutoSuggestBox(AutoSuggestBox auto)
_autoSuggestBox.LostFocus += AutoSuggestBox_LostFocus;

// Setup a binding to the QueryIcon of the Parent if we're the last box.
if (Content is ITokenStringContainer str && str.IsLast)
if (Content is ITokenStringContainer str)
{
// Workaround for https://github.com/microsoft/microsoft-ui-xaml/issues/2568
if (Owner.QueryIcon is FontIconSource fis &&
fis.ReadLocalValue(FontIconSource.FontSizeProperty) == DependencyProperty.UnsetValue)
{
// This can be expensive, could we optimize?
// Also, this is changing the FontSize on the IconSource (which could be shared?)
fis.FontSize = Owner.TryFindResource("TokenizingTextBoxIconFontSize") as double? ?? 16;
}
// We need to set our initial text in all cases.
_autoSuggestBox.Text = str.Text;

var iconBinding = new Binding()
// We only set/bind some properties on the last textbox to mimic the autosuggestbox look
if (str.IsLast)
{
Source = Owner,
Path = new PropertyPath(nameof(Owner.QueryIcon)),
RelativeSource = new RelativeSource() { Mode = RelativeSourceMode.TemplatedParent }
};
// Workaround for https://github.com/microsoft/microsoft-ui-xaml/issues/2568
if (Owner.QueryIcon is FontIconSource fis &&
fis.ReadLocalValue(FontIconSource.FontSizeProperty) == DependencyProperty.UnsetValue)
{
// This can be expensive, could we optimize?
// Also, this is changing the FontSize on the IconSource (which could be shared?)
fis.FontSize = Owner.TryFindResource("TokenizingTextBoxIconFontSize") as double? ?? 16;
}

var iconSourceElement = new IconSourceElement();
var iconBinding = new Binding()
{
Source = Owner,
Path = new PropertyPath(nameof(Owner.QueryIcon)),
RelativeSource = new RelativeSource() { Mode = RelativeSourceMode.TemplatedParent }
};

var iconSourceElement = new IconSourceElement();

iconSourceElement.SetBinding(IconSourceElement.IconSourceProperty, iconBinding);
iconSourceElement.SetBinding(IconSourceElement.IconSourceProperty, iconBinding);

_autoSuggestBox.QueryIcon = iconSourceElement;
_autoSuggestBox.QueryIcon = iconSourceElement;
}
}
}
}
Expand Down Expand Up @@ -156,11 +164,35 @@ private void AutoSuggestBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestB
Owner.RaiseSuggestionChosen(sender, args);
}

private void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
// Called to update text by link:TokenizingTextBox.Properties.cs:TextPropertyChanged
internal void UpdateText(string text)
{
var t = sender.Text.Trim();
if (_autoSuggestBox != null)
{
_autoSuggestBox.Text = text;
}
else
{
void WaitForLoad(object s, RoutedEventArgs eargs)
{
if (_autoSuggestTextBox != null)
{
_autoSuggestTextBox.Text = text;
}

Owner.Text = sender.Text; // Update parent text property
AutoSuggestTextBoxLoaded -= WaitForLoad;
}

AutoSuggestTextBoxLoaded += WaitForLoad;
}
}

private void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
if (!EqualityComparer<string>.Default.Equals(sender.Text, Owner.Text))
{
Owner.Text = sender.Text; // Update parent text property, if different
}

// Override our programmatic manipulation as we're redirecting input for the user
if (UseCharacterAsUser)
Expand All @@ -172,6 +204,8 @@ private void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTex

Owner.RaiseTextChanged(sender, args);

var t = sender.Text?.Trim() ?? string.Empty;

// Look for Token Delimiters to create new tokens when text changes.
if (!string.IsNullOrEmpty(Owner.TokenDelimiter) && t.Contains(Owner.TokenDelimiter))
{
Expand All @@ -195,7 +229,7 @@ private void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTex
}
else
{
sender.Text = tokens[tokens.Length - 1];
sender.Text = tokens[tokens.Length - 1].Trim();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,6 @@
ItemsSource="{Binding Path=Owner.SuggestedItemsSource, RelativeSource={RelativeSource Mode=TemplatedParent}}"
PlaceholderText="{Binding Path=Owner.PlaceholderText, RelativeSource={RelativeSource Mode=TemplatedParent}}"
Style="{StaticResource SystemAutoSuggestBoxStyle}"
Text="{Binding Text, Mode=TwoWay}"
TextBoxStyle="{StaticResource TokenizingTextBoxTextBoxStyle}"/>
</ControlTemplate>
</Setter.Value>
Expand Down
2 changes: 1 addition & 1 deletion UITests/UITests.Tests.MSTest/UITests.Tests.MSTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<PackageReference Include="Microsoft.Toolkit" Version="7.1.2" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<!-- Microsoft.UI.Xaml MSTest Extension -->
<PackageReference Include="MUXTestInfra.MSTest" Version="0.0.4" />
<!-- System packages -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<ItemGroup>
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
</ItemGroup>

<Import Project="..\UnitTests.Notifications.Shared\UnitTests.Notifications.Shared.projitems" Label="Shared" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
<PackageReference Include="MSTest.TestFramework">
<Version>2.1.2</Version>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="System.ValueTuple">
<Version>4.5.0</Version>
</PackageReference>
Expand Down
Loading