ContentView 内的 Xamarin 表单编辑器无法正确调整大小或换行文本
Xamarin forms Editor inside ContentView doesn't resize or wrap text properly
因此,我在代码中声明了一个编辑器,该编辑器绑定到 ListView 的自定义 ViewCell 中 StackLayout 中的 ContentView 的内容 属性,如果编辑器,它要么不会换行文本,要么不会调整大小以适应它。如果我启用 AutoSize,文本不会换行并且会离开屏幕。如果我禁用 AutoSize,编辑器会正确换行文本,但它一次只显示一行文本,并且每当 XAML 热重载刷新屏幕时,文本就会“展开”。我该如何解决这些问题?
我替换了 XAML 中的所有内容和我认为与“...”无关的代码。
我的XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Partylist.Views.ChecklistPage">
...
<ContentPage.Content>
<!--Main layout of the page-->
<StackLayout>
<!--ListView of the checklist items-->
<ListView x:Name="ChecklistView"
ItemSelected="OnItemSelected"
HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<!--These context actions are buttons that appear
when you long press the item (Android) or swipe
left (iOS).-->
<ViewCell.ContextActions>
<MenuItem Clicked="OnDelete"
CommandParameter="{Binding .}"
Text="Delete"
IsDestructive="true"/>
</ViewCell.ContextActions>
<!--This is the actual content-->
<StackLayout Orientation="Horizontal"
Padding="20,5"
VerticalOptions="FillAndExpand">
<ContentView Content="{Binding ItemCheckbox}"/>
<ContentView Content="{Binding ItemEditor}"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
我的代码:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Partylist.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ChecklistPage : ContentPage
{
// Struct for items on the checklist.
struct Item
{
public Editor ItemEditor { get; set; }
public CheckBox ItemCheckbox { get; set; }
}
// Create a list of contact structs to populate the ListView.
ObservableCollection<Item> items;
// Flag for when an item is added to the list.
bool itemAdded = false;
...
// Override for OnAppearing().
protected override void OnAppearing()
{
...
// Set the binding context of the page to itself.
BindingContext = this;
...
// Make the ObservableCOllection reference something.
items = new ObservableCollection<Item>();
// Open a stream to the list that we want to display.
StreamReader listReader = new StreamReader(App.selectedList
.ListFile.FullName);
// Loop through the file and read data into the list.
while (!listReader.EndOfStream)
{
// Create a blank item.
Item newItem = new Item()
{
ItemEditor = new Editor()
{
Text = listReader.ReadLine(),
Placeholder = "New Item",
IsTabStop = true,
//AutoSize = EditorAutoSizeOption.TextChanges
},
ItemCheckbox = new CheckBox()
{
Color = App.selectedList.ListItemColor,
IsChecked = bool.Parse(listReader.ReadLine())
}
};
// Subscribe OnCompleted() to the new item's "Completed"
// event.
newItem.ItemEditor.Completed += OnCompleted;
// Subscribe OnTextChanged() to the new item's
// "TextChanged" event.
newItem.ItemEditor.TextChanged += OnTextChanged;
// Add the new item to the list.
items.Add(newItem);
// Make the ListView update.
ChecklistView.ItemsSource = items;
OnPropertyChanged("contacts");
}
// Once everything is loaded, close the file.
listReader.Close();
}
...
// Function for when the "Add New Contact" button is clicked.
private void OnAddNewItemClicked(object sender, EventArgs e)
{
// Create a blank item.
Item newItem = new Item()
{
ItemEditor = new Editor()
{
Placeholder = "New Item",
IsTabStop = true,
//AutoSize = EditorAutoSizeOption.TextChanges
},
ItemCheckbox = new CheckBox()
{
Color = App.selectedList.ListItemColor,
IsChecked = false
}
};
// Subscribe OnCompleted() to the new item's "Completed"
// event.
newItem.ItemEditor.Completed += OnCompleted;
// Subscribe OnTextChanged() to the new item's
// "TextChanged" event.
newItem.ItemEditor.TextChanged += OnTextChanged;
// Add the new contact to the list.
items.Add(newItem);
// Set the "itemAdded" flag to true.
itemAdded = true;
// Make the ListView update.
ChecklistView.ItemsSource = items;
OnPropertyChanged("contacts");
// Select the new item.
ChecklistView.SelectedItem = items.ElementAt(items.Count - 1);
}
// Function for when an item is selected, used to set the focus to
// a newly added item in the list.
private async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
// Only runs this if an item was added (as opposed to being
// read in from the file).
if (itemAdded)
{
if (e.SelectedItem == null) return;
await Task.Delay(100); // Change the delay time if Focus() doesn't work.
((Item)e.SelectedItem).ItemEditor.Focus();
ChecklistView.SelectedItem = null;
itemAdded = false;
}
}
// Function for when the user presses "Return" on the keyboard in
// an editor.
private void OnCompleted(object sender, EventArgs e)
{
// We just want to unfocus the editor.
((Editor)sender).Unfocus();
}
// Function for when the user types anything in the editor, used
// to make sure it resizes.
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
// Makes the cell resize. The cell is the parent of the
// StackLayout which is the parent of the ContentView which is
// the parent of the Editor that fired the event.
((ViewCell)((Editor)sender).Parent.Parent.Parent)
.ForceUpdateSize();
}
...
}
}
通常当我们使用 Editor 时,我们用 StackLayout 包裹它,这将其最大宽度限制为 StackLayout。但是,在这里,您使用了不限制宽度的 ContentView。它默认为无限宽度,因此它始终是单行显示,您可以尝试将 WidthRequest 添加到 Editor.
ItemEditor = new Editor()
{
Placeholder = "New Item",
IsTabStop = true,
WidthRequest = 200,
AutoSize = EditorAutoSizeOption.TextChanges
}
因此,我在代码中声明了一个编辑器,该编辑器绑定到 ListView 的自定义 ViewCell 中 StackLayout 中的 ContentView 的内容 属性,如果编辑器,它要么不会换行文本,要么不会调整大小以适应它。如果我启用 AutoSize,文本不会换行并且会离开屏幕。如果我禁用 AutoSize,编辑器会正确换行文本,但它一次只显示一行文本,并且每当 XAML 热重载刷新屏幕时,文本就会“展开”。我该如何解决这些问题?
我替换了 XAML 中的所有内容和我认为与“...”无关的代码。
我的XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Partylist.Views.ChecklistPage">
...
<ContentPage.Content>
<!--Main layout of the page-->
<StackLayout>
<!--ListView of the checklist items-->
<ListView x:Name="ChecklistView"
ItemSelected="OnItemSelected"
HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<!--These context actions are buttons that appear
when you long press the item (Android) or swipe
left (iOS).-->
<ViewCell.ContextActions>
<MenuItem Clicked="OnDelete"
CommandParameter="{Binding .}"
Text="Delete"
IsDestructive="true"/>
</ViewCell.ContextActions>
<!--This is the actual content-->
<StackLayout Orientation="Horizontal"
Padding="20,5"
VerticalOptions="FillAndExpand">
<ContentView Content="{Binding ItemCheckbox}"/>
<ContentView Content="{Binding ItemEditor}"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
我的代码:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Partylist.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ChecklistPage : ContentPage
{
// Struct for items on the checklist.
struct Item
{
public Editor ItemEditor { get; set; }
public CheckBox ItemCheckbox { get; set; }
}
// Create a list of contact structs to populate the ListView.
ObservableCollection<Item> items;
// Flag for when an item is added to the list.
bool itemAdded = false;
...
// Override for OnAppearing().
protected override void OnAppearing()
{
...
// Set the binding context of the page to itself.
BindingContext = this;
...
// Make the ObservableCOllection reference something.
items = new ObservableCollection<Item>();
// Open a stream to the list that we want to display.
StreamReader listReader = new StreamReader(App.selectedList
.ListFile.FullName);
// Loop through the file and read data into the list.
while (!listReader.EndOfStream)
{
// Create a blank item.
Item newItem = new Item()
{
ItemEditor = new Editor()
{
Text = listReader.ReadLine(),
Placeholder = "New Item",
IsTabStop = true,
//AutoSize = EditorAutoSizeOption.TextChanges
},
ItemCheckbox = new CheckBox()
{
Color = App.selectedList.ListItemColor,
IsChecked = bool.Parse(listReader.ReadLine())
}
};
// Subscribe OnCompleted() to the new item's "Completed"
// event.
newItem.ItemEditor.Completed += OnCompleted;
// Subscribe OnTextChanged() to the new item's
// "TextChanged" event.
newItem.ItemEditor.TextChanged += OnTextChanged;
// Add the new item to the list.
items.Add(newItem);
// Make the ListView update.
ChecklistView.ItemsSource = items;
OnPropertyChanged("contacts");
}
// Once everything is loaded, close the file.
listReader.Close();
}
...
// Function for when the "Add New Contact" button is clicked.
private void OnAddNewItemClicked(object sender, EventArgs e)
{
// Create a blank item.
Item newItem = new Item()
{
ItemEditor = new Editor()
{
Placeholder = "New Item",
IsTabStop = true,
//AutoSize = EditorAutoSizeOption.TextChanges
},
ItemCheckbox = new CheckBox()
{
Color = App.selectedList.ListItemColor,
IsChecked = false
}
};
// Subscribe OnCompleted() to the new item's "Completed"
// event.
newItem.ItemEditor.Completed += OnCompleted;
// Subscribe OnTextChanged() to the new item's
// "TextChanged" event.
newItem.ItemEditor.TextChanged += OnTextChanged;
// Add the new contact to the list.
items.Add(newItem);
// Set the "itemAdded" flag to true.
itemAdded = true;
// Make the ListView update.
ChecklistView.ItemsSource = items;
OnPropertyChanged("contacts");
// Select the new item.
ChecklistView.SelectedItem = items.ElementAt(items.Count - 1);
}
// Function for when an item is selected, used to set the focus to
// a newly added item in the list.
private async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
// Only runs this if an item was added (as opposed to being
// read in from the file).
if (itemAdded)
{
if (e.SelectedItem == null) return;
await Task.Delay(100); // Change the delay time if Focus() doesn't work.
((Item)e.SelectedItem).ItemEditor.Focus();
ChecklistView.SelectedItem = null;
itemAdded = false;
}
}
// Function for when the user presses "Return" on the keyboard in
// an editor.
private void OnCompleted(object sender, EventArgs e)
{
// We just want to unfocus the editor.
((Editor)sender).Unfocus();
}
// Function for when the user types anything in the editor, used
// to make sure it resizes.
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
// Makes the cell resize. The cell is the parent of the
// StackLayout which is the parent of the ContentView which is
// the parent of the Editor that fired the event.
((ViewCell)((Editor)sender).Parent.Parent.Parent)
.ForceUpdateSize();
}
...
}
}
通常当我们使用 Editor 时,我们用 StackLayout 包裹它,这将其最大宽度限制为 StackLayout。但是,在这里,您使用了不限制宽度的 ContentView。它默认为无限宽度,因此它始终是单行显示,您可以尝试将 WidthRequest 添加到 Editor.
ItemEditor = new Editor()
{
Placeholder = "New Item",
IsTabStop = true,
WidthRequest = 200,
AutoSize = EditorAutoSizeOption.TextChanges
}