Diskuze: WPF Converter

C# .NET .NET (C# a Visual Basic) WPF Converter American English version English version

Avatar
rwn
Člen
Avatar
rwn:

Zdravím, mám takový problém, zkusím to co nejjednodušeji vysvětlit. :) Chtěl bych si naBindovat data z textBoxu do nějaké vlastnosti, já bych ale potřeboval ona data ještě převést na jiná, přesněji přes Converter v XAML. S tímhle by zatím nebyl problém. Problém je v tom, že když si udělám třídu, která onen Converter provádí, tak bych chtěl ono převádění dělat za použití dat z kolekce. Problém je v tom, že nevím jak té třídě onu kolekci z daty dát. Kdybych to měl vysvětlit na příkladu, tak dejme tomu že bych do textboxu psal jen číslo, třeba 2 a ona třída na Converter by mě do oné Bindované vlastnosti poslala item na 2. místě v kolekci. Zajímaloby mě jestli se to takhle dá vubec nějak udělat. Jediné co mě napadá je, že bych měl onu kolekci statickou, ale nepřijde mě to jako nejlepší nápad. Na internetu jsem nic podobného nenašel, přitom mě to přijde jako něco, s čím se muselo setkat hodně lidí pokud to jde nějak řešit. (btw. přes event na kontrolce a převáděním tam bych to dělat nechtěl). Předem děkuji za každý nápad. :)

Odpovědět 14.7.2015 17:39
Co můžeš naprogramovat dnes, neodkládej na zítřek.
Avatar
rwn
Člen
Avatar
rwn:

Co mě tak ještě napadá je, si udělat Singleton, který by v sobě měl onu kolekci s daty, což není problém naprogramovat, ale nejsem si jistý jestli je to programátorsky šťastně řešeno.

Nahoru Odpovědět 15.7.2015 9:58
Co můžeš naprogramovat dnes, neodkládej na zítřek.
Avatar
Odpovídá na rwn
sadlomaslox25:

pres MultiValueCon­verter. Do prvni hodnoty das tu kolekci a vevnitr pretypujes na IList nebo IEnumerable a druha hodnota bude ten index.

Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
 
Nahoru Odpovědět 16.7.2015 20:21
Avatar
rwn
Člen
Avatar
rwn:

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? :)

Nahoru Odpovědět 16.7.2015 23:44
Co můžeš naprogramovat dnes, neodkládej na zítřek.
Avatar
Odpovídá na rwn
sadlomaslox25:

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.

 
Nahoru Odpovědět 17.7.2015 9:38
Avatar
rwn
Člen
Avatar
Odpovídá na sadlomaslox25
rwn:

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 ?

Nahoru Odpovědět 17.7.2015 16:32
Co můžeš naprogramovat dnes, neodkládej na zítřek.
Avatar
Odpovídá na rwn
sadlomaslox25:

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));
    }
}
 
Nahoru Odpovědět 18.7.2015 15:42
Avatar
rwn
Člen
Avatar
Odpovídá na sadlomaslox25
rwn:

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. :D

Editováno 18.7.2015 22:23
Nahoru Odpovědět 18.7.2015 22:21
Co můžeš naprogramovat dnes, neodkládej na zítřek.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 8 zpráv z 8.