В любом случае, чтобы установить «DataContext» строки, совместно используемой столбцами ListView? - PullRequest
0 голосов
/ 22 ноября 2010

Это лучший способ сформулировать мой вопрос, вот сценарий: у меня ListView привязан к коллекции объектов. Каждый из этих объектов имеет свойство UserID, которое является просто ссылочным идентификатором объекта User. В моем ListView я хочу отобразить несколько свойств как объекта, так и User. Для этого я создал класс, который реализует MultiValueConverter, чтобы служить таблицей поиска для пользовательских объектов. Поэтому я использую мультисвязывание, которое передает преобразователю значений UserID, и таблицу поиска по словарю, которая предоставляется базовым ViewModel.

Это все работает отлично и отлично, за исключением того, что я надеюсь, что есть способ, которым я мог бы установить DataContext или что-то из 'строки', которую разделяют столбцы ListView. Таким образом, я мог бы изменить свой конвертер значений так, чтобы он просто возвращал объект User вместо конкретных свойств объекта user. И тогда я мог бы просто связать свойства этого DataContext. Я не хочу создавать новый конвертер значений для каждого пользовательского свойства, которое я хочу показать. Единственный способ сделать это - передать имена свойств в конвертер значений и использовать отражение.

Есть идеи? Я понимаю, что этот DataContext, о котором я мечтаю, - это работа объектов данных, связанных с ListView ItemsSource, но, возможно, я мог бы использовать и кое-что еще. Прикрепленные свойства, кажется, решают все проблемы WPF, которые у меня есть, поэтому я держу пари, что решение будет связано с использованием AttachedProperty для создания этого 'datacontext'

Я уверен, что кто-то скажет мне выставить объект User из самих объектов данных вместо использования какого-то обратного метода использования идентификаторов пользователя и таблицы поиска, НО, я делаю это по причине. спасибо.

<ListView.View>
    <GridView>
        <GridViewColumn>
            <GridViewColumn.Header>User</GridViewColumn.Header>
            <GridViewColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock MinWidth="120">
                        <TextBlock.Text>
                            <MultiBinding Converter="{StaticResource UserIDConverter}">
                                <Binding Path="UserID" />
                                <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=UserControl}" Path="DataContext.Users"/>
                            </MultiBinding>
                        </TextBlock.Text>
                    </TextBlock>
                </DataTemplate>
            </GridViewColumn.CellTemplate>
        </GridViewColumn>
    </GridView>
</ListView.View>

Конвертер:

public class UserIDConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter,
                          System.Globalization.CultureInfo culture)
    {
        int userId = (int)values[0];
        IDictionary<int, PhoneUser> table = values[1] as IDictionary<int, PhoneUser>;
        if (table.ContainsKey(userId))
        {
            PhoneUser user = table[userId];
            return user.LastName;
            //I'd like to just return user !!
        }

        return null;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter,
                                System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

Ответы [ 2 ]

0 голосов
/ 22 ноября 2010

Итак, если я правильно вас понимаю, вы хотите, чтобы ваш конвертер просто возвращал весь PhoneUser объект, а затем каждый столбец должен решить, какое свойство PhoneUser получить?

Если вы действительно настаиваете на этом запутанном методе, я думаю, что ваша идея отражения (передать имя свойства в преобразователь и использовать отражение для возврата значения) была бы лучшей.


Тем не менее, я не могу удержаться от ответа, который вы не хотели слышать (даже если он вам не поможет, он может помочь кому-то еще). Вот что я бы действительно рекомендовал вам сделать ...

  1. Создайте класс, который объединяет ваш текущий объект (скажем, он называется Foo) и PhoneUser.

    public class FooPhoneUser
    {
        Foo Foo { get; set; }
        PhoneUser User { get; set; }
    }
    
  2. Используйте LINQ для объединения этих двух классов:

    var FooPhoneUsers = 
        from
            f in Foos
        join
            pu in PhoneUsers on f.UserId equals pu.Id
        select
            new FooPhoneUser { Foo = f, User = pu };
    
  3. Избавьтесь от всей этой обязательной разметки от вашего GridViewColumn и просто добавьте что-то вроде этого:

    <TextBlock MinWidth="120" Text={Binding User.LastName} />
    

    или

    <TextBlock MinWidth="120" Text={Binding Foo.SomeOtherProp} />
    
0 голосов
/ 22 ноября 2010

Было бы намного проще, если бы вы могли заполнить свой объект данных PhoneUser вместо просто идентификатора, тогда вы могли бы сделать:

<DataTemplate>
  <StackPanel>
    <TextBlock MinWidth="120" Text="{Binding Path="User.FirstName}">
    </TextBlock>
    <TextBlock MinWidth="120" Text="{Binding Path="User.LastName}">
    </TextBlock>
  </StackPanel>
</DataTemplate>

Структура класса будет выглядеть примерно так:

public class myDataObject //The data object you already have.
{
    public string value1;
    public string value2;
    public PhoneUser User; //currently you have "UserID" here.
}

public class PhoneUser
{
    public string FirstName;
    public string LastName;
}

Если вам не подходит извлечение всех пользовательских данных при первой загрузке объекта данных, вы можете использовать стратегию «отложенной загрузки», например:

public class myDataObject //The data object you already have.
{
    public string UserID;
    public string value2;
    private PhoneUser _User; 
    public PhoneUser User
    {
        get
        {
            if(_User==null)
                _User = getUserFromDatabase(UserID);
            return _User;
        }
    }
}

Полагаю, вы могли бы сделать это без каких-либо изменений в структуре вашего кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...