powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / WPF сложный биндинг
23 сообщений из 23, страница 1 из 1
WPF сложный биндинг
    #39220191
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Или не биндинг.

В общем, у листвью в 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
WPF сложный биндинг
    #39220210
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У тебя ровно два телефона? или N?
Если N - надо не StackPanel втыкать, а ItemsControl, вязать на него ItemsSource="{Binding PhonesParsed}" и делать свой ItemTemplate
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220241
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Зы: В случае чисто текстового контента Label отличается от TextBlock-а только наличием поддержки горячей клавиши (&). Так что если не требуется поддержка нетекстового контента или горячей клавиши - можно использовать TextBlock - он вроде как полегче.
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220297
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
WPF сложный биндинг
    #39220320
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А может FlowDocument можно прикрутить?
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220323
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тогда тупо забабахай свой юзерконтрол, формируй в нем разметку хочешь кодом, хочешь xaml-ом, соответственно его и запихнешь в шаблон сетки.
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220326
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AntonariyА может FlowDocument можно прикрутить?
FlowDocument работает без виртуализации вроде, при больших таблицах будет не очень быстро работать и есть множество других ограничений.
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220327
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AntonariyА может FlowDocument можно прикрутить?имхо, это будет тяжеловеснее, если можно обычной разметкой сделать, почему бы нет.
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220376
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProТогда тупо забабахай свой юзерконтрол, формируй в нем разметку хочешь кодом, хочешь xaml-ом, соответственно его и запихнешь в шаблон сетки.Похоже это самый годный вариант.
Соответственно, вопрос: как в юзерконтроле сформировать разметку (кодом или xaml'ом) на основании значения из биндинга?
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220393
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У тебя будет в разметке шаблона
Код: xml
1.
<local:MyUserControl DataContext="{Binding PhonesParsed}" />


Соответственно, в самом юзерконтроле в разметке у тебя уже автоматом будет нужный контекст, то есть можешь привязываться спокойно {Binding SomeProperty} или просто {Binding} (если нужно привязаться ко всему экземпляру, хранящемуся в PhonesParsed).
В коде опять же ты можешь достать объект PhonesParsed из this.DataContext или также создавать кодом байндинги без указания Source (они будут основываться на вышестоящем DataContext-е)
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220408
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
хотя... тут есть подводный камень, если не ошибаюсь. Если ты разместишь юзерконтрол в шаблоне, то обслуживать каждую строку будет его единственный экземпляр. Так что придется разместить его в ресурсе с атрибутом x:Shared="False", чтобы экземпляры были разные
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220413
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Proдостать объект PhonesParsed из this.DataContextи тут еще надо понимать, что на момент создания экземпляра там может быть null, так что надо отслеживать его изменение (через OnPropertyChanged).
Я бы постарался все сделать через разметку. Однако, если в принципе есть возможность все сделать через разметку, то не требовалось бы создавать и юзерконтрол )))
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220428
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, все понял.
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39220436
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как по мне, всё должно выглядеть примерно так:
есть главная модель со списком неких 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
WPF сложный биндинг
    #39220912
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
WPF сложный биндинг
    #39221021
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вытащил 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
WPF сложный биндинг
    #39221050
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не пытайся сам менять DataContext, я за все годы работы с WPF практически ни разу не пользовался этим свойством.
Если кто то пытается, что то делать через свойство DataContext, значит он что то делает неправильно.
контекст данных должен сам автоматически наследоваться и переопределяться.
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39221069
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да я не меняю его, мне прочитать нужно, чтобы получить и распарсить строку и сгенерить на ее основе разметку.
Собственно, два вопроса у меня:
1) почему не работает ItemsControl?
2) Как сделать, чтобы DataConext возвращал свойство, а не весь объект?
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39221075
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
выложи больше кода, больше XAML интересует, не понятно, где от куда ноги растут.

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

Опиши точно и чётко ТЗ, я тебе скину пример по нему.
...
Рейтинг: 0 / 0
WPF сложный биндинг
    #39221105
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
WPF сложный биндинг
    #39221139
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все, разобрался. Нужно было так сделать:

Код: 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
WPF сложный биндинг
    #39221199
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariy,

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

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


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