2015-10-01 6 views
0

Я хочу установить MinWidth столбца сетки, который должен быть суммой фактической ширины метки и кнопки управления внутри другой сетки, помещенной внутри ячейки столбца , Для этой цели я использую класс Converter, но выясню часть XAML. конвертер здесь:Как связать Сумма ширины двух элементов управления до MinWidth другого элемента управления

class StringSumtoIntConverter : IMultiValueConverter 
{ 
    public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture) 
    { 
     int sum = 0; 
     foreach (var item in value) 
     { 
      sum += System.Convert.ToInt32(item); 
     } 

     return sum; 
    } 
    //...Other implementations 
} 

XAML код, который я написал до сих пор:

xmlns:helperClasses="clr-namespace:EmbroidaryManagementSystem_V2._0.HelperClasses" <!--Import class--> 

<helperClasses:StringSumtoIntConverter x:Key="StringSumtoIntConvert"/> <!--Inside Window.Resources tag--> 

<ColumnDefinition Width="48*"> <!--Inside Grid--> 
    <ColumnDefinition.MinWidth> 
     <MultiBinding Converter="{StaticResource StringSumtoIntConvert}"> 
      <Binding Path=""></Binding> 
     </MultiBinding> 
    </ColumnDefinition.MinWidth> 
</ColumnDefinition> 

Полная реализация XAML здесь:

<Window x:Class="EmbroidaryManagementSystem_V2._0.View.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:EmbroidaryManagementSystem_V2._0.View" 
    xmlns:y="clr-namespace:EmbroidaryManagementSystem_V2._0.ViewModel.CollectionsViewModel" 
    xmlns:helperClasses="clr-namespace:EmbroidaryManagementSystem_V2._0.HelperClasses" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="655.512" Width="1120.159" FontSize="24" WindowStartupLocation="CenterScreen" 
    > 
<Window.Resources> 
    <helperClasses:StringSumtoIntConverter x:Key="StringSumtoIntConvert"/> 
</Window.Resources> 
<Window.DataContext> 
    <y:ClientCollectionVM/> 
</Window.DataContext> 
<Grid HorizontalAlignment="Left" Height="622" VerticalAlignment="Top" Width="1110" Background="#FFD6DBE9"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="89*"/> 
     <RowDefinition Height="39*"/> 
     <RowDefinition Height="494*"/> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="137*"/> 
     <ColumnDefinition Width="48*"> 
      <ColumnDefinition.MinWidth> 
       <MultiBinding Converter="{StaticResource StringSumtoIntConvert}"> 
        <Binding Path=""></Binding> 
       </MultiBinding> 
      </ColumnDefinition.MinWidth> 
     </ColumnDefinition> 
    </Grid.ColumnDefinitions> 
    <GridSplitter x:Name="gridSplitter" Grid.Column="1" HorizontalAlignment="Left" Height="533" Grid.Row="1" 
        VerticalAlignment="Top" Width="2" Grid.RowSpan="2"/> 
    <Grid Grid.Column="1" Height="35" Background="#FF657695" 
      Grid.Row="1" VerticalAlignment="Top"> 
     <Label x:Name="lblNotificationsHeader" Content="Notifications" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14.667" Height="30" Foreground="#FFEBF0EE"/> 
     <Button x:Name="btnNotificationsClose" Content="X" 
       Margin="0,5,8,0" VerticalAlignment="Top" Width="20" FontFamily="Verdana" HorizontalAlignment="Right" Background="Transparent" FontSize="13.333" Foreground="Black"/> 
    </Grid> 
</Grid> 

Также есть ошибка: Невозможно применить объект типа «EmbroidaryManagementSystem_V2._0.ViewModel.Coll ectionsViewModel.ClientCollectionVM 'для ввода «System.IConvertible». В строке:

<MultiBinding Converter="{StaticResource StringSumtoIntConvert}"> 
         <Binding Path=""></Binding> 
        </MultiBinding> 

Я не знаю, почему.

ответ

2

Вам необходимо предоставить значения преобразователю в MultiBinding.

<MultiBinding Converter="{StaticResource StringSumtoIntConvert}"> 
    <Binding ElementName="lblNotificationsHeader" Path="ActualWidth" /> 
    <Binding ElementName="btnNotificationsClose" Path="ActualWidth" /> 
</MultiBinding> 

Ошибка в том, что путь пусто, что означает, что он набирает DataContext и пытается передать его в конвертер, который не в состоянии бросить ClientCollectionVM к междунар.

Я не 100% уверен, где вы собираетесь со всем этим, но вы могли бы, вероятно, Никса конвертера и просто сделать:

<Grid.ColumnDefinitions> 
    <ColumnDefinition Width="*" /> 
    <ColumnDefinition Width="Auto" /> 
</Grid.ColumnDefinitions> 

Колонки затем расширить, чтобы соответствовать его содержимому. Конечно, тогда вы хотели бы изменить внутреннюю сетку к StackPanel с горизонтальной ориентацией:

<StackPanel Grid.Row="1" 
       Grid.Column="1" 
       Height="35" 
       VerticalAlignment="Top" 
       Background="#FF657695" 
       Orientation="Horizontal"> 
     <Label x:Name="lblNotificationsHeader" 
       Height="30" 
       HorizontalAlignment="Left" 
       VerticalAlignment="Top" 
       Content="Notifications" 
       FontSize="14.667" 
       Foreground="#FFEBF0EE" /> 
     <Button x:Name="btnNotificationsClose" 
       Margin="0,5,8,0" 
       HorizontalAlignment="Right" 
       VerticalAlignment="Top" 
       Background="Transparent" 
       Content="X" 
       FontFamily="Verdana" 
       FontSize="13.333" 
       Foreground="Black" /> 
    </StackPanel> 

Либо это, либо дать внутреннюю сетку, это собственные определения столбцов, чтобы отделить метку и кнопки вне.

Update

На основе вашего обновления, чтобы добавить GridSplitter, я включил полный пример того, как добиться того, что вы после этого.

Имейте в виду, что в вашем примере GridSplitter действительно изменяет размер левого столбца независимо от того, в каком направлении вы его перетаскиваете, а правый столбец просто расширяется для заполнения. Поэтому наша цель - не иметь MinWidth в правой колонке, а вместо этого - MaxWidth в левой колонке.

Одно быстрое изменение вашего конвертера, так как ActualWidth и ActualHeight - это двойники, давайте сменим конвертер на использование удвоений вместо целых чисел, чтобы мы не попадали в блуждающие пиксели.

public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture) 
    { 
     double sum = 0; 
     foreach (var item in value) 
     { 
      sum += System.Convert.ToDouble(item); 
     } 

     return sum; 
    } 

Мы собираемся поставить GridSplitter в его собственной колонке, установить, что ширину столбцов, чтобы "2" установить ширину первого ColumnDefinition к "4*" и третий "*". "4*" действительно просто случайное число, размер звезд зависит от процентов, поэтому 4 не всегда будут работать, как раз в этом случае.

Нам также необходимо добавить некоторые колонки во внутреннюю сетку, мы дадим им имя и используем эти элементы, чтобы получить ширину для нашего MultiBinding. Мы делаем это вместо того, чтобы получать ширину от самих элементов, потому что ActualWidth не включает поля.

<Grid Background="#FFD6DBE9"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="89*" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="494*" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="4*" /> 
     <ColumnDefinition Width="2" /> 
     <ColumnDefinition Width="*"> 
      <ColumnDefinition.MinWidth> 
       <MultiBinding Converter="{StaticResource StringSumtoIntConvert}"> 
        <Binding ElementName="cdNotificationHeaderLabel" Path="ActualWidth" /> 
        <Binding ElementName="cdNotificationHeaderButton" Path="ActualWidth" /> 
       </MultiBinding> 
      </ColumnDefinition.MinWidth> 
     </ColumnDefinition> 
    </Grid.ColumnDefinitions> 
    <GridSplitter x:Name="gridSplitter" 
        Grid.Row="1" 
        Grid.RowSpan="2" 
        Grid.Column="1" 
        Width="2" 
        ResizeBehavior="PreviousAndNext" /> 
    <Grid Grid.Row="1" 
      Grid.Column="2" 
      Height="35" 
      Background="#FF657695"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition x:Name="cdNotificationHeaderLabel" Width="Auto" /> 
      <ColumnDefinition Width="*" /> 
      <ColumnDefinition x:Name="cdNotificationHeaderButton" Width="Auto" /> 
     </Grid.ColumnDefinitions> 
     <Label x:Name="lblNotificationsHeader" 
       Margin="0 0 5 0" 
       HorizontalAlignment="Left" 
       VerticalAlignment="Center" 
       Content="Notifications" 
       FontSize="14.667" 
       Foreground="#FFEBF0EE" /> 
     <Button x:Name="btnNotificationsClose" 
       Grid.Column="2" 
       HorizontalAlignment="Right" 
       VerticalAlignment="Center" 
       Background="Transparent" 
       Content="X" 
       FontFamily="Verdana" 
       FontSize="13.333" 
       Foreground="Black" /> 
    </Grid> 
</Grid> 

Все, что сказал, я бы рекомендовал получения пользовательского элемента управления от GridSplitter и регулировать его таким образом, но выше, должны помочь, чтобы вы и работает.

+0

Это сработало, но теперь возникла другая проблема. На самом деле есть разделитель между столбцами (я повторно добавил его код, который был ранее удален по ошибке по ошибке). И проблема заключается в том, что я изменяю размер вправо, а метка уведомлений выходит за границу Grid, ее ActualWidth уменьшается (пока я заметил использование отладчика), и конвертер называется повторно с уменьшенной шириной каждый раз. Я хочу, чтобы этот ActualWidth был установлен как самое начальное значение. –

+0

Создание ширины первого и второго столбцов для «*» и «Авто» не помогло. Я также попытался установить MinWidth внутренней сетки, и это тоже не помогло. Я поместил ярлык и кнопку в том же столбце и строке только из-за отсутствия очевидной необходимости отделить их. –

+0

Ну, основная концепция, которой я отсутствовала, - горизонтальные и вертикальные выравнивания GridSplitter. Я поместил GridSplitter в свой собственный, как вы предложили, а затем сделал оба выравнивания «Центр». Таким образом, я смог контролировать размер как первого, так и третьего столбцов, после чего мне пришлось поддерживать MinWidth TabControl в первом столбце. Так что спасибо за тонну за вашу помощь. Я избегал каких-либо кодовых вещей в этом представлении, потому что я новичок в WPF, и я просто хотел поэкспериментировать в XAML. –

1

Вы не указываете ничего в привязке, поэтому его передача в контексте данных, являющемся виртуальной машиной. VM не конвертируется в int. Вам нужно передать {Binding ElementName = btnNotificationsClose, Path = ActualWidth} и ​​то же самое для lblNotificationsHeader.

Честно говоря, похоже, что вы слишком усложняете ситуацию. Строка/столбцы сетки не изменяются по размеру, если вы не используете сплиттер, которым вы не являетесь.

+0

На самом деле я использую сплиттер, я просто удалил его в редактировании, просто подумав, чтобы обеспечить простоту. извините за любое неудобство. –

+0

Да, это сработало. Ричард Прециози тоже ответил на это. –

+0

Я повторно добавил его. Я имею в виду код сплиттера. –