Отказ от ответственности:
Это просто способ выполнить требования, установленные в Исходном сообщении (ОП), и ни в коем случае не подразумевать, что код, который он включает, является наилучшим из возможных или предназначен для производства. кодЭТО ПРОСТО ПУТЬ , ЧТОБЫ ДОСТИГНУТЬ, ЧТО ТРЕБУЕТ ОП.
Давайте создадим Page ( ListView.xaml ) с ListView , который перечисляет пару пунктов, которые ссылаются на главы книги. Каждый элемент при нажатии запускает страницу с содержанием этой главы.
Кроме того, в верхней части этой ListView Page есть SearchBar
: когдапри выполнении поиска приложение проверит, содержит ли какой-либо из страниц, на которые ссылаются элементы, искомый текст.
ListView.xaml:
<StackLayout>
<SearchBar SearchButtonPressed="SearchBar_SearchButtonPressed" TextChanged="SearchBar_TextChanged"/>
<ListView x:Name="listView"
ItemTapped="listView_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Chapter}"
Detail="{Binding Description}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Находясь в коде позади, мы устанавливаем ItemsSource
ListView и определяем EventHandlers для поиска (Бонус: обратите внимание на EventHandler SearchBar_TextChanged
, чтобы вернуться ксписок оригиналов при очистке панели поиска!):
ListView.xaml.cs:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using Xamarin.Forms;
namespace SearchContent
{
public partial class ListView : ContentPage
{
ObservableCollection<Content> contents { get; set; }
public ListView()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
contents = new ObservableCollection<Content>()
{
new Content("Chapter 1", "Description of Chapter 1", new Page1()),
new Content("Chapter 2", "Description of Chapter 2", new Page2()),
};
listView.ItemsSource = contents;
}
private void listView_ItemTapped(object sender, ItemTappedEventArgs e)
{
Navigation.PushAsync(((Content)e.Item).ChapterPage);
}
private void SearchBar_SearchButtonPressed(object sender, EventArgs e)
{
String textToSearch = ((SearchBar)sender).Text;
var contentsFiltered = contents.Where(item => ((Interface1)item.ChapterPage).PageText.Contains(textToSearch));
ObservableCollection<Content> newContents = new ObservableCollection<Content>(contentsFiltered);
listView.ItemsSource = null;
listView.ItemsSource = newContents;
}
private void SearchBar_TextChanged(object sender, TextChangedEventArgs e)
{
if(String.IsNullOrEmpty(e.NewTextValue))
{
listView.ItemsSource = null;
listView.ItemsSource = contents;
}
}
}
public class Content
{
public String Chapter { get; set; }
public String Description { get; set; }
public Page ChapterPage { get; set; }
public Content(String chapter, String description, Page chapterPage)
{
Chapter = chapter;
Description = description;
ChapterPage = chapterPage;
}
}
}
Теперь вам просто нужны страницыс текстом: Page1 и Page2 .
Прежде всего я определяю Интерфейс Interface1
, который будут реализованы на этих страницах. Этот интерфейс используется для определения одного свойства: PageText
. Благодаря реализации этого интерфейса в Page1 и Page2 я смог преобразовать каждый элемент в ListView в Interface1
в EventHandler SearchBar_SearchButtonPressed
in ListView.xaml.cs .
Interface1.cs :
interface Interface1
{
string PageText { get; set; }
}
А теперь страницы:
Page1.xaml
<StackLayout>
<Label Text="{Binding PageText}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
Page1.xaml.cs :
public partial class Page1 : ContentPage,Interface1
{
public String PageText { get; set; }
public Page1()
{
PageText =
"This is the display of the inquiry of Herodotus of Halicarnassus, " +
"so that things done by man not be forgotten in time, and that great " +
"and marvelous deeds, some displayed by the Hellenes, some by the " +
"barbarians, not lose their glory, including among others what was the " +
"cause of their waging war on each other. ";
InitializeComponent();
BindingContext = this;
}
}
И аналогично
Page2.xaml
<StackLayout>
<Label Text="{Binding PageText}"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
Page2.xaml.cs
public partial class Page2 : ContentPage, Interface1
{
public String PageText { get; set; }
public Page2()
{
PageText =
"The Persian learned men say that the Phoenicians were the cause " +
"of the dispute. These (they say) came to our seas from the sea " +
"which is called Red,1 and having settled in the country which " +
"they still occupy, at once began to make long voyages. Among other " +
"places to which they carried Egyptian and Assyrian merchandise, " +
"they came to Argos";
InitializeComponent();
BindingContext = this;
}
}
Но что, если вы ДОЛЖНЫ читать сами ярлыки? Хорошо, это не очень хорошая практика (поскольку это означало бы, что вы сохраняете ссылки на эти объекты и занимаете ресурсы), и я не могу представить себе случай, когда это ДОЛЖНО быть.
Но если бы мне пришлось это сделать, я бы подумал, что можно было бы определить метки либо как Public
, либо как Public static
в Page2 . В первом случае вы должны сохранить ссылку на Page2 myPage2 = new Page2()
, чтобы прочитать Public Label (myPage2.myPublicLabel
). Во втором случае это только метка, на которую остается ссылка, и ее можно затем извлечь как Page2.mystaticLabel
. Естественно, сначала нужно проверить, назначен ли ярлык и т. Д. ...
Пока что проблема, описанная в ОП, должна быть решена, тем не менее, возможно, стоит попробоватьдругой подход:
Вместо создания Page1 , Page2 и т. д. вы, возможно, захотите расширить ваши объекты (те, которые питают ListView и вызвал Content
в моем примере выше), чтобы включить String
свойство ChapterText
, которое содержит текст, предназначенный для отображения на других страницах. Если это так, вы можете создать универсальный Page , конструктор которого принимает один из этих объектов в качестве параметра и использует ChapterText
в качестве текста для Page . После этого вы можете выполнить поиск из SearchBar
без приведения к Interface1
, но непосредственно в свойстве ChapterText
элементов ...