Diskuze: WPF Converter
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 8 zpráv z 8.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
pres MultiValueConverter. Do prvni hodnoty das tu kolekci a vevnitr pretypujes na IList nebo IEnumerable a druha hodnota bude ten index.
Děkuji za odpověd, tímto způsobem jsem to už začal řešit, ale zaseknul jsem se na jedné věci. Že když takto přes třídu co provádí MultiValueConverter si převedu hodnoty, tak nevím jak tento výsledek dál předat. Vypadá to přibližně takto:
<TextBox>
<TextBox.Text>
<MultiBinding Converter="{StaticResource textConverter}">
<Binding Path="Kolekce1" ElementName="mainWindow" />
<Binding Path="Kolekce2" ElementName="mainWindow" />
</MultiBinding>
</TextBox.Text>
</TextBox>
Přičemž já bych chtěl takto získaný výsledek po převodu Bindovat do DependencyProperty, něco ve smyslu
<TextBox Text="{Binding mojeDependencyProperty}">
což ale nejde, protože by se text nastavoval víckrát. Nenapadá tě co s tím?
tak to vyres v ramci ViewModelu. udelej si ve ViewModelu 3 property. tu kolekci, index vybrane veci z te kolekce a pak referenci na tu vybranou vec z kolekce. podle potreby to zesynchronizuje jak potrebujes. jednoduzsi je nektere z tech vlastnosti dat jako read only.
Zajímavý nápad, a jak bych pak takto vytvořenou třídu zapsal v XAML, to bych jako Bindoval ten objekt reprezentující ony 3 vlastnosti a byl by to klasický ValueConverter ?
prvni varianta stim conventorem vypada asi takto
<StackPanel Name="view1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel.Resources>
<wpfTest:MyConverter x:Key="con" />
</StackPanel.Resources>
<TextBlock Text="Mesta"/>
<ComboBox Name="combo" ItemsSource="{Binding Data}" DisplayMemberPath="Key" SelectedValuePath="Value" />
<TextBlock Text="Cislo ulice"/>
<Slider Minimum="1" Name="slider" Maximum="{Binding ElementName=combo, Path=SelectedValue.Count}" TickPlacement="TopLeft" SmallChange="1" IsSnapToTickEnabled="True"/>
<TextBlock Text="Nazev ulice"/>
<TextBlock TextAlignment="Center" >
<TextBlock.Text>
<MultiBinding Converter="{StaticResource con}">
<Binding ElementName="combo" Path="SelectedValue"/>
<Binding ElementName="slider" Path="Value"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
public class MyConverter:IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
try
{
var data = values[0] as IList;
var position = int.Parse(values[1].ToString());
return data[position - 1];
}
catch
{
return "N/A";
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class ViewModelV1
{
public Dictionary<string, List<string>> Data { get; set; }
public ViewModelV1()
{
Data = new Dictionary<string, List<string>>()
{
{"Praha", new List<string>() {"Nova", "Zelena", "Oranzova"}},
{"Brno", new List<string>() {"Polni", "Horní"}},
{"Ostrava", new List<string>() {"Stodolní",}},
};
}
}
druha varianta stim rozsirenym viewmodelem vypada asi takto
<StackPanel Grid.Column="1" Name="view2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="Mesta"/>
<ComboBox ItemsSource="{Binding Data}" SelectedItem="{Binding SelectedCity}" DisplayMemberPath="Name" />
<TextBlock Text="Cislo ulice"/>
<Slider Minimum="1" Maximum="{Binding SelectedCity.Streets.Count}" Value="{Binding SelectedStreetIndex}" TickPlacement="TopLeft" SmallChange="1" IsSnapToTickEnabled="True"/>
<TextBlock Text="Nazev ulice"/>
<TextBlock TextAlignment="Center" Text="{Binding SelectedStreetName}"/>
</StackPanel>
public class ViewModelV2:INotifyPropertyChanged
{
private City _selectedCity;
private int _selectedStreetIndex;
public List<City> Data { get; set; }
public class City
{
public string Name { get; set; }
public List<string> Streets { get; set; }
}
public ViewModelV2()
{
Data = new List<City>()
{
new City()
{
Name = "Praha",
Streets = new List<string>()
{"Nova", "Zelena", "Oranzova"}
},
new City()
{
Name = "Brno",
Streets = new List<string>()
{"Polni", "Horní"}
},
new City()
{
Name = "Ostrava",
Streets = new List<string>()
{"Stodolní"}
},
};
}
public City SelectedCity
{
get { return _selectedCity; }
set
{
_selectedCity = value;
SelectedStreetIndex = 1;
OnPropertyChanged();
}
}
public int SelectedStreetIndex
{
get { return _selectedStreetIndex; }
set
{
_selectedStreetIndex = value;
OnPropertyChanged();
OnPropertyChanged("SelectedStreetName");
}
}
public string SelectedStreetName
{
get
{
try
{
return SelectedCity.Streets[SelectedStreetIndex - 1];
}
catch
{
return "N/A";
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Tohle mě až tak moc nepomohlo. Nakonec jsem to vyřešil trochu jinak. Při ConvertBack přenastavuju vlastnost na daném objektu (ten je v rámci převáděcí třídy jako private) a vracím prázdné pole. Při Convert se podívám co má daný (private) objekt v dané vlastnosti a vracím vypočítaný text. Každopádně děkuju za pomoc, kdybys neodepsal, tak bych se na to asi vykašlal a nechal to jako klasický event při změně na textBoxu, tak jako dík, tě můžu aspon označit jako řešitele.
Zobrazeno 8 zpráv z 8.