Гость
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / WPF сложный биндинг / 23 сообщений из 23, страница 1 из 1
20.04.2016, 14:10
    #39220191
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Или не биндинг.

В общем, у листвью в DataContext находится коллекция, в ItemTemplate к полям привязаны ТекстБлоки через {Binding FieldName}, а одно из полей содержит список телефонов. Нужно распарсить значение, каждый телефон обернуть ссылкой и вывести в поле ListViewItem'а.

Допустим, в свойстве PhonesParsed, принадлежащем коллекции, я превращаю текст телефонов в такую разметку:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
                        <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1">
                            <StackPanel Orientation="Horizontal">
                                <Label Padding="0">Тел:</Label>
                                <Label Padding="0">
                                    <Hyperlink Click="Dial">123123123</Hyperlink>
                                </Label>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <Label Padding="0">Тел:</Label>
                                <Label Padding="0">
                                    <Hyperlink Click="Dial">23452345345</Hyperlink>
                                </Label>
                            </StackPanel>
                        </StackPanel>


Как теперь воткнуть ее в элемент с {Binding PhonesParsed}?

Или это как-то совсем по-другому делается?
...
Рейтинг: 0 / 0
20.04.2016, 14:23
    #39220210
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
У тебя ровно два телефона? или N?
Если N - надо не StackPanel втыкать, а ItemsControl, вязать на него ItemsSource="{Binding PhonesParsed}" и делать свой ItemTemplate
...
Рейтинг: 0 / 0
20.04.2016, 14:48
    #39220241
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Зы: В случае чисто текстового контента Label отличается от TextBlock-а только наличием поддержки горячей клавиши (&). Так что если не требуется поддержка нетекстового контента или горячей клавиши - можно использовать TextBlock - он вроде как полегче.
...
Рейтинг: 0 / 0
20.04.2016, 15:20
    #39220297
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Shocker.ProУ тебя ровно два телефона? или N?
Если N - надо не StackPanel втыкать, а ItemsControl, вязать на него ItemsSource="{Binding PhonesParsed}" и делать свой ItemTemplateУ меня N телефонов вперемешку с текстом.
Прочитал эту ссылку http://www.wpf-tutorial.com/list-controls/itemscontrol/ представление об ItemTemplate поимел.

Допустим, распарсил я поле с телефонами в коллекцию, возвращаемую свойством PhonesParsed. Но там же не только лишь телефоны.
Например такая последовательность: текст - номер - текст - перенос строки - текст - номер - перенос строки - номер .
Стак панелями легко разбить на строки, а в гиперссылки должны заворачиваться только номера, но не текст. При генерации статической разметки в виде текста, тут проблема всего одна - воткнуть ее с помощью биндинга.

Если же делать по правилам, то я это представил себе так. Допустим, каждый из типов элементов коллекции я оформлю как отдельный класс со свойством value. Тогда PhonesParsed будет возвращать набор элементов типа
clsText - clsPhone - clsText - clsNewline - clsText - clsPhone - clsNewline - clsPhone
Как в этом случае сделать чтобы для clsText выводился обычный Label, для clsPhone Label с гиперлинком, а по clsNewline происходил перенос строки - в соответствующем порядке?
...
Рейтинг: 0 / 0
20.04.2016, 15:34
    #39220320
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
А может FlowDocument можно прикрутить?
...
Рейтинг: 0 / 0
20.04.2016, 15:38
    #39220323
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Тогда тупо забабахай свой юзерконтрол, формируй в нем разметку хочешь кодом, хочешь xaml-ом, соответственно его и запихнешь в шаблон сетки.
...
Рейтинг: 0 / 0
20.04.2016, 15:40
    #39220326
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
AntonariyА может FlowDocument можно прикрутить?
FlowDocument работает без виртуализации вроде, при больших таблицах будет не очень быстро работать и есть множество других ограничений.
...
Рейтинг: 0 / 0
20.04.2016, 15:40
    #39220327
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
AntonariyА может FlowDocument можно прикрутить?имхо, это будет тяжеловеснее, если можно обычной разметкой сделать, почему бы нет.
...
Рейтинг: 0 / 0
20.04.2016, 16:07
    #39220376
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Shocker.ProТогда тупо забабахай свой юзерконтрол, формируй в нем разметку хочешь кодом, хочешь xaml-ом, соответственно его и запихнешь в шаблон сетки.Похоже это самый годный вариант.
Соответственно, вопрос: как в юзерконтроле сформировать разметку (кодом или xaml'ом) на основании значения из биндинга?
...
Рейтинг: 0 / 0
20.04.2016, 16:15
    #39220393
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
У тебя будет в разметке шаблона
Код: xml
1.
<local:MyUserControl DataContext="{Binding PhonesParsed}" />


Соответственно, в самом юзерконтроле в разметке у тебя уже автоматом будет нужный контекст, то есть можешь привязываться спокойно {Binding SomeProperty} или просто {Binding} (если нужно привязаться ко всему экземпляру, хранящемуся в PhonesParsed).
В коде опять же ты можешь достать объект PhonesParsed из this.DataContext или также создавать кодом байндинги без указания Source (они будут основываться на вышестоящем DataContext-е)
...
Рейтинг: 0 / 0
20.04.2016, 16:21
    #39220408
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
хотя... тут есть подводный камень, если не ошибаюсь. Если ты разместишь юзерконтрол в шаблоне, то обслуживать каждую строку будет его единственный экземпляр. Так что придется разместить его в ресурсе с атрибутом x:Shared="False", чтобы экземпляры были разные
...
Рейтинг: 0 / 0
20.04.2016, 16:23
    #39220413
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Shocker.Proдостать объект PhonesParsed из this.DataContextи тут еще надо понимать, что на момент создания экземпляра там может быть null, так что надо отслеживать его изменение (через OnPropertyChanged).
Я бы постарался все сделать через разметку. Однако, если в принципе есть возможность все сделать через разметку, то не требовалось бы создавать и юзерконтрол )))
...
Рейтинг: 0 / 0
20.04.2016, 16:33
    #39220428
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Спасибо, все понял.
...
Рейтинг: 0 / 0
20.04.2016, 16:37
    #39220436
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Как по мне, всё должно выглядеть примерно так:
есть главная модель со списком неких Person'ов аля: IEnumerable<Person> Persones
в классе Person, есть свойство Phones типа IEnumerable<Phone> или любое другое перечисляемое (при этом сам экземпляр может быть Observable, не важно)
Теперь ты делаешь шаблон для Person и для Phone
Берешь ItemsControl и ItemTemplate указываешь шаблон для Person, а в шаблон Person'а, будет свой ItemsControl с шаблона для телефонов.

и еще момент, TextBlock, это не просто текстовый элемент :) это гораздо больше, у него есть замечательно свойство Inlines, в котором можно указать инлайн текстовые элементы (как раз из FlowDocument)
Если быть проще:
<TextBlock>
<TextBlock.Inlines>
<Run Text="Phone: "/>
<Hyperlink Click="Dial">123123123</Hyperlink>
</TextBlock.Inlines>
</TextBlock>

Ссылка, кстати это тоже Inline элемент :)
Это кстати благоприятно скажется на производительности, если TextBlock'ов будет слишком много.
...
Рейтинг: 0 / 0
21.04.2016, 10:25
    #39220912
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Roman MejtesКак по мне, всё должно выглядеть примерно так:
есть главная модель со списком неких Person'ов аля: IEnumerable<Person> Persones
в классе Person, есть свойство Phones типа IEnumerable<Phone> или любое другое перечисляемое (при этом сам экземпляр может быть Observable, не важно)
Теперь ты делаешь шаблон для Person и для Phone
Берешь ItemsControl и ItemTemplate указываешь шаблон для Person, а в шаблон Person'а, будет свой ItemsControl с шаблона для телефонов.Последовал этой схеме. Шаблон для всей записи и конкретно поля с телефонами (лишнее убрал):

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
 
    <Style x:Key="ListViewDir" TargetType="{x:Type ListView}">
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid Name="gridItem" Margin="0">
                        <!--TextBlock Margin="5 5 5 0" Text="{Binding Telephone}" Grid.Column="0" Grid.Row="0" FontSize="14" -->
                        <StackPanel Grid.Column="0" Grid.Row="0">
                            <ItemsControl >
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <local:ctlPhonesParser DataContext="{Binding PhonesParsed}"/>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>


В биндинге такое свойство:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
    Dim mPhones As New List(Of String)

    Public ReadOnly Property PhonesParsed As List(Of String)
        Get
            Return mPhones
        End Get
    End Property

    <XmlElement("Telephone")>
    Public Property Telephone As String
        Get
            Return mPhone
        End Get
        Set(value As String)
            mPhone = value
            mPhones = Split(value, vbCrLf).ToList
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Telephone"))
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("PhonesParsed"))
        End Set
    End Property


ctlPhonesParser пока что без разметки, в нем такой код:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    Private Sub ctlPhonesParser_DataContextChanged(sender As Object, e As DependencyPropertyChangedEventArgs) Handles Me.DataContextChanged
        If Not Me.DataContext Is Nothing Then
            Debug.Print(Me.DataContext.ToString)
        End If
    End Sub

    Private Sub ctlPhonesParser_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        If Not Me.DataContext Is Nothing Then
            Debug.Print(Me.DataContext.ToString)
        End If
    End Sub

По идее ctlPhonesParser должен получать строку, содержащую номер, и рисовать TextBlock.Inlines. Однако ничего с ctlPhonesParser не происходит, даже Loaded не срабатывает.
Что я делаю не так?
...
Рейтинг: 0 / 0
21.04.2016, 11:32
    #39221021
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Вытащил ctlPhonesParser из ItemsControl напрямую в грид:

Код: xml
1.
<local:ctlPhonesParser Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" DataContext="{Binding PhonesParsed}"/>


Контрол начал создаваться, но Me.DataContext ссылается на всю запись, а не конкретно на свойство PhonesParsed. По идее контролу незачем знать имя свойства, ибо если вдруг оно сменит название, то код Me.DataContext.PhonesParsed перестанет работать.

Что-то с ItemsControl не так, хотелось бы ctlPhonesParser.DataContext связать с элементом коллекции PhonesParsed, а не всей записью контакта.
...
Рейтинг: 0 / 0
21.04.2016, 11:50
    #39221050
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
не пытайся сам менять DataContext, я за все годы работы с WPF практически ни разу не пользовался этим свойством.
Если кто то пытается, что то делать через свойство DataContext, значит он что то делает неправильно.
контекст данных должен сам автоматически наследоваться и переопределяться.
...
Рейтинг: 0 / 0
21.04.2016, 12:07
    #39221069
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Да я не меняю его, мне прочитать нужно, чтобы получить и распарсить строку и сгенерить на ее основе разметку.
Собственно, два вопроса у меня:
1) почему не работает ItemsControl?
2) Как сделать, чтобы DataConext возвращал свойство, а не весь объект?
...
Рейтинг: 0 / 0
21.04.2016, 12:15
    #39221075
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
выложи больше кода, больше XAML интересует, не понятно, где от куда ноги растут.

Попробуй ListView заменить на ItemsControl\ListBox

Опиши точно и чётко ТЗ, я тебе скину пример по нему.
...
Рейтинг: 0 / 0
21.04.2016, 12:47
    #39221105
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Roman Mejtes,

Со вторым вопросом разобрался.
По первому вопросу:

код
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
  <ListView x:Name="lvDirectory" ItemsSource="{Binding}"  Style="{StaticResource ListViewDir}" >
  </ListView>

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="clsResourceEvents"
                    xmlns:local="clr-namespace:Dialer">

  <Style x:Key="ListViewDir" TargetType="{x:Type ListView}">
    <Setter Property="ItemTemplate">
      <Setter.Value>
        <DataTemplate>
          <Grid Name="gridItem" Margin="0">
            <local:ctlPhonesParser DataContext="{Binding PhonesParsed}">
              <!-- работает -->
            </local:ctlPhonesParser>
            <StackPanel Grid.Column="0" Grid.Row="0" Grid.RowSpan="2">
                <ItemsControl>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                          <local:ctlPhonesParser DataContext="{Binding PhonesParsed}">
                            <!-- не работает -->
                          </local:ctlPhonesParser>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </StackPanel>
          </Grid>
        </DataTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

<UserControl x:Class="ctlPhonesParser"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

</UserControl>

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
Dim dc As ObservableCollection(Of DirectoryEntry) = getList()
lvDirectory.DataContext = dc

Public Class DirectoryEntry
    Implements INotifyPropertyChanged

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged

    Dim mContact As String
    Dim mPhone As String
    Dim mNote As String
    Dim mPhones As New List(Of String)

    Public ReadOnly Property PhonesParsed As List(Of String)
        Get
            Return mPhones
        End Get
    End Property

    <XmlElement("Telephone")>
    Public Property Telephone As String
        Get
            Return mPhone
        End Get
        Set(value As String)
            mPhone = value
            mPhones = Split(value, vbCrLf).ToList
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Telephone"))
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("PhonesParsed"))
        End Set
    End Property

End Class

ТЗ:
В листвью нужно отобразить список контактов - ObservableCollection(Of DirectoryEntry).
В одной из ячеек в каждой строке списка контактов нужно отобразить список телефонов, связанных с контактом - List(Of String)
Каждый телефон должен отобразиться в экземпляре ctlPhonesParser, разметка которого будет создана динамически.

Проблема: экземпляры ctlPhonesParser, размещенные в ItemsControl, не создаются.
...
Рейтинг: 0 / 0
21.04.2016, 13:05
    #39221139
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Все, разобрался. Нужно было так сделать:

Код: xml
1.
2.
3.
4.
5.
6.
7.
                            <ItemsControl ItemsSource="{Binding PhonesParsed}">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <local:ctlPhonesParser DataContext="{Binding}"/>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>

Почему-то в текстовых примерах в справочниках, что я смотрел, свойство ItemsSource не использовалось, и типа на словах все работало.
...
Рейтинг: 0 / 0
21.04.2016, 13:47
    #39221199
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Antonariy,

DataContext="{Binding}" - абсолютно бессмысленное действо, это связывание нужно удалить
...
Рейтинг: 0 / 0
21.04.2016, 16:35
    #39221469
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WPF сложный биндинг
Roman MejtesAntonariy,

DataContext="{Binding}" - абсолютно бессмысленное действо, это связывание нужно удалитьУдалил. Работает без него :)
...
Рейтинг: 0 / 0
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / WPF сложный биндинг / 23 сообщений из 23, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]