Как мне моделировать данные в многоязычном редакторе данных в WPF с MVVM? - PullRequest
1 голос
/ 25 марта 2010

Существуют ли передовые практики, которым необходимо следовать при разработке модели / ViewModel для представления данных в приложении, которое будет просматривать / редактировать эти данные на нескольких языках? Наш класс верхнего уровня, назовем его «Курс», содержит несколько свойств коллекции, например, Books и TopicsCovered, каждое из которых может иметь свойство коллекции среди своих данных. Какую структуру классов я должен реализовать для хранения данных для определенных свойств на нескольких языках?

Например, данные должны представлять course1.Books.First (). Заголовок на разных языках и course1.TopicsCovered.First (). Имя на разных языках. Нам нужно приложение, которое может редактировать любые данные для одного данного курса на любом из доступных языков, а также редактировать данные, не относящиеся к конкретному языку, например, «Автор книги» (т.е. course1.Books.First (). Автор). У нас возникают проблемы с выяснением того, как лучше настроить модель для включения привязки в представлении XAML.

Например, заменяем ли мы (в одноязычной модели) каждую строку на набор экземпляров LanguageSpecificString? Таким образом, чтобы получить название на текущем языке:

course1.Books.First().Title.Where(lss => lss.Language==CurrentLanguage).SingleOrDefault()

Если мы сделаем это, мы не сможем легко связать любое значение на одном данном языке, только с набором значений языка, таких как ItemsControl.

<TextBox Text={Binding Title.???} />  <!-- no way to bind to the current language title -->

Заменим ли мы курс высшего уровня на набор языковых курсов? Итак, чтобы получить название на текущем языке:

course1.GetLanguage(CurrentLanguage).Books.First().Title

Если мы это сделаем, мы можем легко работать только с одним языком одновременно; мы могли бы хотеть, чтобы представление показывало один язык и позволяло пользователю редактировать другой.

<TextBox Text={Binding Title} />  <!-- good -->
<TextBlock Text={Binding ??? } />  <!-- no way to bind to the other language's title-->

Кроме того, недостатком является то, что они не представляют нейтрально-языковые данные как таковые; каждое свойство (например, Author) может показаться на нескольких языках. Даже нестроковые свойства будут на нескольких языках.

Есть ли вариант между этими двумя? Есть ли другой способ, о котором мы не думаем?

Я понимаю, что это несколько расплывчато, но, похоже, это довольно распространенная проблема для разработки.

Примечание. Речь идет не о предоставлении многоязычного пользовательского интерфейса, а о гибком редактировании многоязычных данных.

Редактировать: поэтому вопрос в том, как мы должны моделировать классы? Примерно так:

Class Course { 
    ObservableCollection<Book> Books
    ObservableCollection<Topic> TopicsCovered
}
Class Book {
    ObservableCollection<LanguageSpecificString> Title
    String Author
}
Class Topic {
    ObservableCollection<LanguageSpecificString> Name
}
Class LanguageSpecificString {
    String LanguageCode
    String Value
}

Или это должно быть что-то вроде:

Class MultilingualCourse { 
    Course GetLanguage(string languageCode)
}
Class Course { 
    ObservableCollection<Book> Books
    ObservableCollection<Topic> TopicsCovered
}
Class Book {
    String Title
    String Author
}
Class Topic {
    String Name
}

Или что-то совсем другое?

Ответы [ 4 ]

1 голос
/ 26 марта 2010

Как насчет этого (я пропустил уведомление об изменении в моем примере):

public class BookViewModel
{
    private readonly Book book;
    private readonly CultureInfo viewCulture;

    // constructor
    public BookViewModel(Book book, CultureInfo viewCulture)
    {
        this.book = book;
        this.viewCulture = viewCulture;
    }

    public string OriginalTitle
    {
        get { return this.book.OriginalTitle; }
        set { this.book.OriginalTitle = value; }
    }

    public string TranslatedTitle
    {
        get { return this.book.GetCultureSpecificTitle(this.viewCulture); }
        set { this.book.SetCultureSpecificTitle(this.viewCulture, value); }
    }

    public string Author
    {
        get { return this.book.Author; }
        set { this.book.Author = value; }
    }
}

Вы также упоминаете о необходимости создания представлений, в которых задействовано несколько языков. Здесь я предположил, что вы создаете интерфейс перевода, и вам нужно только показать исходный язык и целевой язык перевода.

Но если вам нужно иметь возможность показывать любые два языка рядом, вы все равно можете построить модель представления с viewCulture1 и viewCulture2 и соответствующими открытыми свойствами, такими как Title1 и Title2. Или же вы могли бы создать составные представления, в которых разные части представления имеют модели представления с разными ассоциированными языками (см. Использование вложенных моделей представления и шаблонов данных в примере Джоша Смита ).

Вы также можете представить культуру представления как изменяемое свойство и привязать к нему поле со списком, чтобы динамически позволить пользователю переключать представление между языками и т. Д.

Для модели я использовал методы GetCultureSpecificX и SetCultureSpecificX, но альтернативные механизмы (например, ваше предложение IEnumerable<LanguageSpecificString>) также можно адаптировать к простому строковому свойству в модели представления.

0 голосов
/ 15 апреля 2010

Мы решили пойти проще, чем эти ответы, и просто заменить каждую переводимую строку на Словарь (language, value). Конечно, мы можем пожелать Словарь в будущем. Это близко к моему первому ответу в оригинальном сообщении.

0 голосов
/ 26 марта 2010

Вместо того, чтобы возиться с вашим переплетом и дизайном вашего класса, подумайте об обезьянах с DataTemplateSelector s. Например, если у вас есть строковый класс с поддержкой локали, который вы хотите отобразить в TextBox, если он на текущем языке, и в TextBlock, если это не так, вы можете поместить эту точку принятия решения в селектор шаблона. Каждый случай, скажем,

<ContentControl Content="{Binding LocaleAwareStringProperty}"
                ContentTemplateSelector="{StaticResource StringTemplateSelector}"/>

будет обработано с соответствующим контролем. (Конечно, вы можете установить ContentTemplateSelector в стиле, который упростит XAML.)

0 голосов
/ 25 марта 2010

Если я вас правильно понимаю, вы хотите локализовать данные, а также представление данных? Т.е. при перечислении Книги колонка «Автор» будет на выбранном языке? Для локализации пользовательского интерфейса мы реализовали что-то вроде этого. http://www.wpftutorial.net/LocalizeMarkupExtension.html Для локализации данных, я думаю, вам нужно иметь столбец, указывающий, какую локаль вы запрашиваете. Данные на английском языке будут отделены от данных на французском языке и т. Д.

Я не понимаю твою обязательную проблему. Имя привязки не должно меняться. Не должны ваши свойства модели. Если у вас есть свойство «Автор», оно всегда останется таковым. Если вы хотите отобразить это на экране на другом языке, то вы используете способ, перечисленный выше, или другой, чтобы локализовать отображаемые строки. То же самое касается сообщений. Таким образом, пользователь может выбрать свой язык, и вы отобразите все на своем языке.

...