2010-05-03 3 views
1

내 컬렉션의 항목을 표시하는 ViewBox가있는 WPF 앱을 사용하여 결과에 2 열 그리드를 표시합니다.WPF : 데이터 양에 따라 ViewBox의 스타일을 변경하십시오.

제 컬렉션의 항목 수에 따라 열 수를 변경하고 싶습니다. 예를 들어 목록에 < 개의 항목이 10 개있는 경우 1 열만 표시하십시오. 내 목록에 10 개의 항목이 있으면 2 개의 항목으로 표시하십시오. 내 목록에 20 개의 항목이 있으면 3 개의 항목을 표시하십시오.

<Style x:Key="myStyle" TargetType="{x:Type ItemsControl}"> 
    <Setter Property=ItemsControl.ItemsPanel"> 
     <Setter.Value> 
     <ItemsPanelTemplate> 
      <UniformGrid Columns="2" /> 
     </ItemsPanelTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

가 어떻게 위의 요구 사항이 코드가 작동 할 수 있습니다 :

<Viewbox> 
    <ItemsControl ItemsSource="{Binding myCollection}" Style="{DynamicResource myStyle}" /> 
</Viewbox> 

여기 myStyle 현재 정의 내용은 다음과 같습니다 여기

내가 현재 가지고 무엇인가? 감사.

답변

2

당신은 항목 수에 Columns 속성을 결합하고, 컬럼의 수를 결정과 같이하는 적절한 IValueConverter을 사용할 수 있습니다 : 당신이에 RelativeSource를 추가해야 할 수도 있습니다

<UniformGrid Columns="{Binding Items.Count, Converter={local:ItemsToColumnConverter}}" /> 

주 이 바인딩을 작동시키기 위해서.

그리고 그에게 IValueConverter 유사한 :

물론
public class ItemsToColumnConverter : IValueConverter 
{ 
    // ... 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     int numItems = (int)value; 
     if (numItems < 10) 
      return 1; 
     else if (numItems < 20) 
      return 2; 
     else if (numItems < 30) 
      return 3; 
     else 
      return numItems/10; 
    } 

    public object ConvertBack(...) 
    { 
     throw new NotSupportedException(); 
    } 
} 

, 당신은 또한 컨버터를 사용하는 모든 경우-ELSEIF - 다른 물건을 피할 또 다른 수학의 논리를 만들 수 있습니다.

+0

+1. 좋고 깨끗합니다. – Gishu

+0

다른 WPF noobs가이 코드를 볼 경우, (적어도 나를 위해) 그대로 컴파일되지 않는다는 점에 유의하십시오. Converter 클래스에'ValueConversion' 속성을 추가하고 그 타입의 정적 리소스를 생성 한 다음'Converter = {StaticResource myConverter}'를 설정해야했습니다. 아마도 나는 뭔가를 놓치고 있지만 그 것이 효과가있었습니다. – Pat

+0

그냥 명확히하기 위해 : 1) 'StaticResource'를 선언 할 필요가 없습니다. 변환기가 존재하는 네임 스페이스를'xmlns : local'으로 지정하고 위와 같이'Converter = {local : ItemsToColumnConverter}'와 같이 사용하십시오. 2) 'ValueConversion' 속성은 필요하지 않습니다. [MSDN] (http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx) : * "구현을 ValueConversionAttribute로 장식하는 것이 좋습니다. .. "이것은 코드가 컴파일되는 것을 막지는 못합니다. 'ConvertBack (...)'메소드의 정의는 불완전합니다 (단지 예입니다!). – gehho

1

DataTrigger를 사용하여 특정 스타일을 설정하는 방법은 어떻습니까? 작은 크기의 '크기 인 경우 열'튜플이있는 경우 가능할 수 있습니다.
동일한 ItemPanelStyleSelector가 없다는 것을 알 수 있습니다 (ItemContainerStyleSelector와 유사).

업데이트 : 작동합니다. 다른 응답도 살펴 보겠습니다. 값 변환기를 사용하여 Columns 값을 ValueConverter.Convert (list.Count)에 의해 반환 된 값에 바인드하십시오.

public string[] Options { get; set;} 

    public bool NeedsTwoColumns 
    { 
     get 
     { 
      return this.Options.Length > 4; 
     } 
    } 

//Xaml 
<ListBox ItemsSource="{Binding Options}"> 
      <ListBox.Style> 
       <Style> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding NeedsTwoColumns}" Value="True"> 
          <Setter Property="ItemsControl.ItemsPanel"> 
           <Setter.Value> 
            <ItemsPanelTemplate> 
             <UniformGrid Columns="2"/> 
            </ItemsPanelTemplate> 
           </Setter.Value> 
          </Setter> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </ListBox.Style> 
     </ListBox> 
    <ListBox ItemsSource="{Binding Options}"> 
     <ListBox.Resources> 
      <local:MyConverter x:Key="ListLengthToColumnCountConverter"/> 
     </ListBox.Resources> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <UniformGrid Columns="{Binding Options.Length, Converter={StaticResource ListLengthToColumnCountConverter}}"/> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
    </ListBox> 

//ValueConverter 
public class MyConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     int listSize = (int)value; 
     return (int)(listSize/3); 
    } ... 
+0

좋아, 좋은 소리 ... 어떻게 작동합니까? –

+0

@ 브렛 - 업데이트를 참조하십시오. 나는 ValueConverter를 사용하는 접근법을 좋아하지 않는다. – Gishu

관련 문제