WPF

2012-08-08 7 views
6

में गतिशील प्रतिशत-आधारित चौड़ाई शायद आप इसे समझने में मेरी सहायता कर सकते हैं: मेरे पास एक शब्दकोश और एक आइटम नियंत्रण है जो उस शब्दकोश से जुड़ा हुआ है। प्रत्येक प्रविष्टि की कुंजी आइटम नियंत्रण में प्रत्येक आइटम की सामग्री निर्धारित करती है और मान प्रत्येक आइटम की चौड़ाई निर्धारित करता है। इसके साथ बड़ी समस्या: चौड़ाई प्रतिशत मान है, इसलिए यह मुझे बताती है कि, उदाहरण के लिए, मेरे आइटम को आकार में अपने माता-पिता का 20% होना चाहिए।WPF

मैं इसे कैसे प्राप्त कर सकता हूं? मुझे पता है कि ग्रिड स्टार-आधारित चौड़ाई के साथ काम करने में सक्षम हैं, लेकिन चूंकि मुझे ग्रिड की शुरुआत में ग्रिडडिफिनिशन को परिभाषित करना है, इसलिए मैं इसे आइटम्स कंट्रोल.इटम टेम्पलेट में नहीं कर सकता।

वर्तमान कोड:

<ItemsControl ItemsSource="{Binding Distribution}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <Grid IsItemsHost="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <!-- I NEED THIS TO BE A CERTAIN PERCENTAGE IN WIDTH --> 
       <Label Content="{Binding Key.Text}" Foreground="{Binding Key.Color}"/> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 

इस पर कोई भी विचार? क्या इसे हल करने का कोई शानदार तरीका है?

धन्यवाद!

स्पष्टीकरण: प्रतिशत आइटमकंट्रोल माता-पिता पर आधारित होना चाहिए!

और दूसरा एक: प्रत्येक आइटम को ग्रिड का एक स्तंभ होना चाहिए, न कि पंक्ति। तो मुझे एक ही पंक्ति में एक दूसरे के बगल में रहने के लिए सभी वस्तुओं की आवश्यकता है।

समाधान:

आपकी मदद के लिए धन्यवाद, इस समस्या को Multibinding का उपयोग करने और ItemsControl की ActualWidth लिए बाध्यकारी द्वारा हल किया जा सकता है। इस तरह, जब भी आइटम नियंत्रण आकार में बदल जाता है, आइटम भी बदल जाते हैं। एक ग्रिड की जरूरत नहीं है। यह समाधान केवल एक सापेक्ष चौड़ाई बनाता है, लेकिन वही समाधान निश्चित रूप से वस्तुओं की ऊंचाई पर लागू किया जा सकता है।

XAML:: यह एक लघु संस्करण, एक और अधिक विस्तृत विवरण के लिए नीचे देख रहा है

<ItemsControl ItemsSource="{Binding Distribution}" Name="itemsControl" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel IsItemsHost="True" Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Label Content="{Binding Key.Text}" 
         Foreground="{Binding Key.Color}"> 
        <Label.Width> 
         <MultiBinding Converter="{StaticResource myConverter}"> 
          <Binding Path="Value"/> 
          <Binding Path="ActualWidth" ElementName="itemsControl"/> 
         </MultiBinding> 
        </Label.Width> 
       </Label> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 

कनवर्टर:

class MyConverter : IMultiValueConverter 
{ 
    public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture) 
    { 
     //[1] contains the ItemsControl.ActualWidth we binded to, [0] the percentage 
     //In this case, I assume the percentage is a double between 0 and 1 
     return (double)value[1] * (double)value[0]; 
    } 

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

और वह चाल करना चाहिए!

+0

क्या माता-पिता का 20%? आइटम्स कंट्रोल, लेबल, या कुछ और के माता-पिता? – jtimperley

+0

क्या मतलब है "मुझे ग्रिड की शुरुआत में ग्रिडडिफिनिशन को परिभाषित करना है?" आप अपने ग्रिड को 'DataTemplate' में इसके बजाय परिभाषित कर सकते हैं - इसे' आइटम पैनेल टेम्पलेट 'में होने की आवश्यकता नहीं है। –

+0

हाय। मेरा संपादन देखें, 20% आइटमकंट्रोल माता-पिता (या लेबल अभिभावक का 20% होना चाहिए। चूंकि मैं दोनों दिशाओं में लेबल्स पैरेंट स्ट्रेच कर सकता हूं) यह वही होगा। ग्रिड की शुरुआत के लिए: हाँ, मैं अपने ग्रिड को डेटा टेम्पलेट में परिभाषित कर सकता हूं, लेकिन फिर प्रत्येक आइटम का अपना ग्रिड होगा, जो काम नहीं करेगा, या मैं यहां कुछ देख रहा हूं? – BlackWolf

उत्तर

7

के बीच खाली जगह बंटवारे आवश्यकता होगी।

अद्यतन

MultiBinding आपकी मदद करेगा।यहाँ नमूना है:

1) XAML:

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="114" Width="404"> 
    <Grid> 
     <Grid.Resources> 
      <local:RelativeWidthConverter x:Key="RelativeWidthConverter"/> 
     </Grid.Resources> 

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

     <ItemsControl ItemsSource="{Binding}" 
         x:Name="itemsControl"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <Rectangle Fill="Green" Margin="5" Height="20" HorizontalAlignment="Left"> 
         <Rectangle.Width> 
          <MultiBinding Converter="{StaticResource RelativeWidthConverter}"> 
           <Binding Path="RelativeWidth"/> 
           <Binding Path="ActualWidth" ElementName="itemsControl"/> 
          </MultiBinding> 
         </Rectangle.Width> 
        </Rectangle> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
    </Grid> 
</Window> 

2) कनवर्टर:

public class RelativeWidthConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return ((Double)values[0] * (Double)values[1])/100.0; 
    } 

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

3) दृश्य मॉडल:

public class ViewModel : ViewModelBase 
{ 
    public ViewModel() 
    { 
    } 

    public Double RelativeWidth 
    { 
     get { return relativeWidth; } 
     set 
     { 
      if (relativeWidth != value) 
      { 
       relativeWidth = value; 
       OnPropertyChanged("RelativeWidth"); 
      } 
     } 
    } 
    private Double relativeWidth; 
} 

4) कोड-पीछे:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new[] 
     { 
      new ViewModel { RelativeWidth = 20 }, 
      new ViewModel { RelativeWidth = 40 }, 
      new ViewModel { RelativeWidth = 60 }, 
      new ViewModel { RelativeWidth = 100 }, 
     }; 
    } 
} 
बदलते समय

MultiBinding बाध्यकारी लक्ष्य को अपडेट करने के लिए बल।

+0

यह वादा किया गया लगता है, लेकिन काम नहीं लग रहा है। जब कनवर्टर कहा जाता है, तो आइटम्स कंट्रोल का वास्तविक विडियो 0 है, क्योंकि यह अभी तक तैयार नहीं हुआ है। हालांकि, मुझे एक अच्छी दिशा की तरह लगता है। – BlackWolf

+1

@ ब्लैकवॉल्फ ने उत्तर अपडेट किया। – Dennis

+0

आपको बहुत धन्यवाद, मल्टीबाइंडिंग एक आकर्षण की तरह काम किया! जब मैंने ActualWidth बदल दिया, तो मैंने बाध्यकारी मैन्युअल रूप से अद्यतन करने का प्रयास किया, लेकिन यह काम नहीं किया। Multibinding के साथ यह ठीक काम करता है। स्वच्छ और अच्छा समाधान! – BlackWolf

0

ItemTemplate में आप Grid डालने का प्रयास कर सकते हैं। यह Grid में वास्तविक सामग्री के लिए 2 कॉलम: 1 और खाली स्थान के लिए एक होगा। IValueConverter की सहायता से संभवतः आप अपने डिक्शनरी के Value का उपयोग करके इन कॉलम की चौड़ाई को बांधने में सक्षम होना चाहिए।

सामग्री केंद्रित करने की जरूरत है, तो आप 3 कॉलम बनाने के लिए, आप IValueConverter लागू कर सकते हैं कॉलम 0 और 2

+0

चौड़ाई को बाध्य न करें, कॉलमडिफिनिशन पर साझा आकार समूह समूह का उपयोग करें। – jtimperley

+0

मुझे लगता है कि यह मेरी मदद नहीं है, मेरा संपादन देखें। मुझे प्रत्येक आइटम को एक कॉलम और सभी वस्तुओं को एक दूसरे के बगल में गठबंधन करने की आवश्यकता है, इसलिए दुर्भाग्यवश, मैं रिक्त स्थान के साथ काम नहीं कर सकता। – BlackWolf

0

मुझे एक आवश्यकता थी जो ग्रिड का उपयोग नहीं कर सका।

मैंने एक ContentControl बनाया जो मुझे गतिशील प्रतिशत चौड़ाई/ऊंचाई जोड़ने के लिए सामग्री को लपेटने की अनुमति देता है।

/// <summary> 
/// This control has a dynamic/percentage width/height 
/// </summary> 
public class FluentPanel : ContentControl, IValueConverter 
{ 
    #region Dependencie Properties 

    public static readonly DependencyProperty WidthPercentageProperty = 
     DependencyProperty.Register("WidthPercentage", typeof(int), typeof(FluentPanel), new PropertyMetadata(-1, WidthPercentagePropertyChangedCallback)); 

    private static void WidthPercentagePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 
    { 
     ((FluentPanel)dependencyObject).OnWidthPercentageChange(); 
    } 

    public int WidthPercentage 
    { 
     get { return (int)GetValue(WidthPercentageProperty); } 
     set { SetValue(WidthPercentageProperty, value); } 
    } 

    public static readonly DependencyProperty HeightPercentageProperty = 
     DependencyProperty.Register("HeightPercentage", typeof(int), typeof(FluentPanel), new PropertyMetadata(-1, HeightPercentagePropertyChangedCallback)); 

    private static void HeightPercentagePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 
    { 
     ((FluentPanel)dependencyObject).OnHeightPercentageChanged(); 
    } 

    public int HeightPercentage 
    { 
     get { return (int)GetValue(HeightPercentageProperty); } 
     set { SetValue(HeightPercentageProperty, value); } 
    } 

    #endregion 

    #region Methods 

    private void OnWidthPercentageChange() 
    { 
     if (WidthPercentage == -1) 
     { 
      ClearValue(WidthProperty); 
     } 
     else 
     { 
      SetBinding(WidthProperty, new Binding("ActualWidth") { Source = Parent, Converter = this, ConverterParameter = true }); 
     } 
    } 

    private void OnHeightPercentageChanged() 
    { 
     if (HeightPercentage == -1) 
     { 
      ClearValue(HeightProperty); 
     } 
     else 
     { 
      SetBinding(HeightProperty, new Binding("ActualHeight") { Source = Parent, Converter = this, ConverterParameter = false }); 
     } 
    } 

    #endregion 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     if ((bool)parameter) 
     { 
      // width 
      return (double)value * (WidthPercentage * .01); 
     } 
     else 
     { 
      // height 
      return (double)value * (HeightPercentage * .01); 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 
संबंधित मुद्दे